forked from VoxeLibre/VoxeLibre
Merge pull request 'Overhaul breeding' (#1633) from jordan4ibanez/MineClone2:mineclone5 into mineclone5
Reviewed-on: MineClone2/MineClone2#1633
This commit is contained in:
commit
4add3b286c
|
@ -164,6 +164,7 @@ dofile(api_path .. "sound_handling.lua")
|
||||||
dofile(api_path .. "death_logic.lua")
|
dofile(api_path .. "death_logic.lua")
|
||||||
dofile(api_path .. "mob_effects.lua")
|
dofile(api_path .. "mob_effects.lua")
|
||||||
dofile(api_path .. "projectile_handling.lua")
|
dofile(api_path .. "projectile_handling.lua")
|
||||||
|
dofile(api_path .. "breeding.lua")
|
||||||
|
|
||||||
|
|
||||||
mobs.spawning_mobs = {}
|
mobs.spawning_mobs = {}
|
||||||
|
@ -244,7 +245,6 @@ 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,
|
|
||||||
jump = def.jump ~= false,
|
jump = def.jump ~= false,
|
||||||
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,
|
||||||
|
@ -264,8 +264,6 @@ function mobs:register_mob(name, def)
|
||||||
env_damage_timer = 0,
|
env_damage_timer = 0,
|
||||||
tamed = false,
|
tamed = false,
|
||||||
pause_timer = 0,
|
pause_timer = 0,
|
||||||
horny = false,
|
|
||||||
hornytimer = 0,
|
|
||||||
gotten = false,
|
gotten = false,
|
||||||
health = 0,
|
health = 0,
|
||||||
reach = def.reach or 3,
|
reach = def.reach or 3,
|
||||||
|
@ -297,7 +295,6 @@ function mobs:register_mob(name, def)
|
||||||
owner_loyal = def.owner_loyal,
|
owner_loyal = def.owner_loyal,
|
||||||
facing_fence = false,
|
facing_fence = false,
|
||||||
|
|
||||||
|
|
||||||
_cmi_is_mob = true,
|
_cmi_is_mob = true,
|
||||||
|
|
||||||
pushable = def.pushable or true,
|
pushable = def.pushable or true,
|
||||||
|
@ -330,6 +327,25 @@ function mobs:register_mob(name, def)
|
||||||
skittish = def.skittish,
|
skittish = def.skittish,
|
||||||
lifetimer_reset = 30, --30 seconds
|
lifetimer_reset = 30, --30 seconds
|
||||||
lifetimer = 30, --30 seconds
|
lifetimer = 30, --30 seconds
|
||||||
|
|
||||||
|
--breeding stuff
|
||||||
|
breed_timer = 0,
|
||||||
|
breed_lookout_timer = 0,
|
||||||
|
breed_distance = def.breed_distance or 1.5, --how far away mobs have to be to begin actual breeding
|
||||||
|
breed_lookout_timer_goal = 30, --30 seconds (this timer is for how long the mob looks for a mate)
|
||||||
|
breed_timer_cooloff = 5*60, -- 5 minutes (this timer is for how long the mob has to wait before being bred again)
|
||||||
|
bred = false,
|
||||||
|
follow = def.follow, --this item is also used for the breeding mechanism
|
||||||
|
follow_distance = def.follow_distance or 2,
|
||||||
|
baby_size = def.baby_size or 0.5,
|
||||||
|
baby = false,
|
||||||
|
grow_up_timer = 0,
|
||||||
|
grow_up_goal = 20*60, --in 20 minutes the mob grows up
|
||||||
|
special_breed_timer = 0, --this is used for the AHEM AHEM part of breeding
|
||||||
|
|
||||||
|
backup_visual_size = def.visual_size,
|
||||||
|
backup_collisionbox = collisionbox,
|
||||||
|
backup_selectionbox = def.selectionbox or def.collisionbox,
|
||||||
--end j4i stuff
|
--end j4i stuff
|
||||||
|
|
||||||
-- MCL2 extensions
|
-- MCL2 extensions
|
||||||
|
|
|
@ -6,6 +6,7 @@ local math_round = math.round
|
||||||
local vector_multiply = vector.multiply
|
local vector_multiply = vector.multiply
|
||||||
local vector_add = vector.add
|
local vector_add = vector.add
|
||||||
local vector_new = vector.new
|
local vector_new = vector.new
|
||||||
|
local vector_distance = vector.distance
|
||||||
|
|
||||||
local minetest_yaw_to_dir = minetest.yaw_to_dir
|
local minetest_yaw_to_dir = minetest.yaw_to_dir
|
||||||
local minetest_get_item_group = minetest.get_item_group
|
local minetest_get_item_group = minetest.get_item_group
|
||||||
|
@ -67,7 +68,8 @@ local land_state_list_wandering = {"stand", "walk"}
|
||||||
|
|
||||||
local land_state_switch = function(self, dtime)
|
local land_state_switch = function(self, dtime)
|
||||||
|
|
||||||
--do math after sure not attacking or running away
|
--do math before sure not attacking, following, or running away so continue
|
||||||
|
--doing random walking for mobs if all states are not met
|
||||||
self.state_timer = self.state_timer - dtime
|
self.state_timer = self.state_timer - dtime
|
||||||
|
|
||||||
--only run away
|
--only run away
|
||||||
|
@ -76,18 +78,39 @@ local land_state_switch = function(self, dtime)
|
||||||
if self.run_timer > 0 then
|
if self.run_timer > 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
--continue
|
--continue
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--ignore everything else if breeding
|
||||||
|
if self.breed_lookout_timer and self.breed_lookout_timer > 0 then
|
||||||
|
self.state = "breed"
|
||||||
|
return
|
||||||
|
--reset the state timer to get the mob out of
|
||||||
|
--the breed state
|
||||||
|
elseif self.state == "breed" then
|
||||||
|
self.state_timer = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
--ignore everything else if following
|
||||||
|
if mobs.check_following(self) and
|
||||||
|
(not self.breed_lookout_timer or (self.breed_lookout_timer and self.breed_lookout_timer == 0)) and
|
||||||
|
(not self.breed_timer or (self.breed_timer and self.breed_timer == 0)) then
|
||||||
|
self.state = "follow"
|
||||||
|
return
|
||||||
|
--reset the state timer to get the mob out of
|
||||||
|
--the follow state - not the cleanest option
|
||||||
|
--but the easiest
|
||||||
|
elseif self.state == "follow" then
|
||||||
|
self.state_timer = 0
|
||||||
|
end
|
||||||
|
|
||||||
--only attack
|
--only attack
|
||||||
if self.hostile and self.attacking then
|
if self.hostile and self.attacking then
|
||||||
self.state = "attack"
|
self.state = "attack"
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--if finally reached here then do random wander
|
||||||
|
|
||||||
if self.state_timer <= 0 then
|
if self.state_timer <= 0 then
|
||||||
self.state_timer = math.random(4,10) + math.random()
|
self.state_timer = math.random(4,10) + math.random()
|
||||||
self.state = land_state_list_wandering[math.random(1,#land_state_list_wandering)]
|
self.state = land_state_list_wandering[math.random(1,#land_state_list_wandering)]
|
||||||
|
@ -98,10 +121,40 @@ end
|
||||||
-- states are executed here
|
-- states are executed here
|
||||||
local land_state_execution = function(self,dtime)
|
local land_state_execution = function(self,dtime)
|
||||||
|
|
||||||
|
--[[ -- this is a debug which shows the timer and makes mobs breed 100 times faster
|
||||||
|
print(self.breed_timer)
|
||||||
|
if self.breed_timer > 0 then
|
||||||
|
self.breed_timer = self.breed_timer - (dtime * 100)
|
||||||
|
if self.breed_timer <= 0 then
|
||||||
|
self.breed_timer = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
]]--
|
||||||
|
|
||||||
--no collisionbox exception
|
--no collisionbox exception
|
||||||
if not self.object:get_properties() then
|
if not self.object:get_properties() then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--timer to time out looking for mate
|
||||||
|
if self.breed_lookout_timer and self.breed_lookout_timer > 0 then
|
||||||
|
self.breed_lookout_timer = self.breed_lookout_timer - dtime
|
||||||
|
--looking for mate failed
|
||||||
|
if self.breed_lookout_timer <= 0 then
|
||||||
|
self.breed_lookout_timer = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--cool off after breeding
|
||||||
|
if self.breed_timer and self.breed_timer > 0 then
|
||||||
|
self.breed_timer = self.breed_timer - dtime
|
||||||
|
--do this to skip the first check, using as switch
|
||||||
|
if self.breed_timer <= 0 then
|
||||||
|
self.breed_timer = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
local collisionbox = self.object:get_properties().collisionbox
|
local collisionbox = self.object:get_properties().collisionbox
|
||||||
|
@ -144,6 +197,26 @@ local land_state_execution = function(self,dtime)
|
||||||
end
|
end
|
||||||
|
|
||||||
mobs.lock_yaw(self)
|
mobs.lock_yaw(self)
|
||||||
|
elseif self.state == "follow" then
|
||||||
|
|
||||||
|
--always look at players
|
||||||
|
mobs.set_yaw_while_following(self)
|
||||||
|
|
||||||
|
--check distance
|
||||||
|
local distance_from_follow_person = vector_distance(self.object:get_pos(), self.following_person:get_pos())
|
||||||
|
|
||||||
|
--don't push the player if too close
|
||||||
|
if self.follow_distance < distance_from_follow_person then
|
||||||
|
mobs.set_mob_animation(self, "run")
|
||||||
|
mobs.set_velocity(self,self.run_velocity)
|
||||||
|
|
||||||
|
if mobs.jump_check(self) == 1 then
|
||||||
|
mobs.jump(self)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
mobs.set_mob_animation(self, "stand")
|
||||||
|
mobs.set_velocity(self,0)
|
||||||
|
end
|
||||||
|
|
||||||
elseif self.state == "walk" then
|
elseif self.state == "walk" then
|
||||||
|
|
||||||
|
@ -246,6 +319,48 @@ local land_state_execution = function(self,dtime)
|
||||||
mobs.projectile_attack_walk(self,dtime)
|
mobs.projectile_attack_walk(self,dtime)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
elseif self.state == "breed" then
|
||||||
|
|
||||||
|
mobs.breeding_effect(self)
|
||||||
|
|
||||||
|
local mate = mobs.look_for_mate(self)
|
||||||
|
|
||||||
|
--found a mate
|
||||||
|
if mate then
|
||||||
|
mobs.set_yaw_while_breeding(self,mate)
|
||||||
|
mobs.set_velocity(self, self.walk_velocity)
|
||||||
|
|
||||||
|
--smoosh together basically
|
||||||
|
if vector_distance(self.object:get_pos(), mate:get_pos()) <= self.breed_distance then
|
||||||
|
mobs.set_mob_animation(self, "stand")
|
||||||
|
if self.special_breed_timer == 0 then
|
||||||
|
self.special_breed_timer = 2 --breeding takes 2 seconds
|
||||||
|
end
|
||||||
|
|
||||||
|
self.special_breed_timer = self.special_breed_timer - dtime
|
||||||
|
if self.special_breed_timer <= 0 then
|
||||||
|
|
||||||
|
--pop a baby out, it's a miracle!
|
||||||
|
local baby_pos = vector.divide(vector.add(self.object:get_pos(), mate:get_pos()), 2)
|
||||||
|
local baby_mob = minetest.add_entity(pos, self.name, minetest.serialize({baby = true, grow_up_timer = self.grow_up_goal, bred = true}))
|
||||||
|
|
||||||
|
self.special_breed_timer = 0
|
||||||
|
self.breed_lookout_timer = 0
|
||||||
|
self.breed_timer = self.breed_timer_cooloff
|
||||||
|
|
||||||
|
mate:get_luaentity().special_breed_timer = 0
|
||||||
|
mate:get_luaentity().breed_lookout_timer = 0
|
||||||
|
mate:get_luaentity().breed_timer = self.breed_timer_cooloff -- can reuse because it's the same mob
|
||||||
|
end
|
||||||
|
else
|
||||||
|
mobs.set_mob_animation(self, "walk")
|
||||||
|
end
|
||||||
|
--couldn't find a mate, just stand there until the player pushes it towards one
|
||||||
|
--or the timer runs out
|
||||||
|
else
|
||||||
|
mobs.set_mob_animation(self, "stand")
|
||||||
|
mobs.set_velocity(self,0)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -697,8 +812,8 @@ mobs.mob_step = function(self, dtime)
|
||||||
end
|
end
|
||||||
|
|
||||||
--despawn mechanism
|
--despawn mechanism
|
||||||
--don't despawned tamed mobs
|
--don't despawned tamed or bred mobs
|
||||||
if not self.tamed then
|
if not self.tamed and not self.bred then
|
||||||
self.lifetimer = self.lifetimer - dtime
|
self.lifetimer = self.lifetimer - dtime
|
||||||
if self.lifetimer <= 0 then
|
if self.lifetimer <= 0 then
|
||||||
self.lifetimer = self.lifetimer_reset
|
self.lifetimer = self.lifetimer_reset
|
||||||
|
@ -735,6 +850,24 @@ mobs.mob_step = function(self, dtime)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--baby grows up
|
||||||
|
if self.baby then
|
||||||
|
--print(self.grow_up_timer)
|
||||||
|
--catch missing timer
|
||||||
|
if not self.grow_up_timer then
|
||||||
|
self.grow_up_timer = self.grow_up_goal
|
||||||
|
end
|
||||||
|
|
||||||
|
self.grow_up_timer = self.grow_up_timer - dtime
|
||||||
|
|
||||||
|
--baby grows up!
|
||||||
|
if self.grow_up_timer <= 0 then
|
||||||
|
self.grow_up_timer = 0
|
||||||
|
mobs.baby_grow_up(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--do custom mob instructions
|
--do custom mob instructions
|
||||||
if self.do_custom then
|
if self.do_custom then
|
||||||
|
|
|
@ -213,4 +213,47 @@ mobs.handle_explosion_animation = function(self)
|
||||||
visual_size_modified.y = visual_size_modified.y * explosion_timer_adjust
|
visual_size_modified.y = visual_size_modified.y * explosion_timer_adjust
|
||||||
|
|
||||||
self.object:set_properties({visual_size = visual_size_modified})
|
self.object:set_properties({visual_size = visual_size_modified})
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--this is used when a mob is following player
|
||||||
|
mobs.set_yaw_while_following = function(self)
|
||||||
|
|
||||||
|
if self.object:get_properties().automatic_face_movement_dir then
|
||||||
|
self.object:set_properties{automatic_face_movement_dir = false}
|
||||||
|
end
|
||||||
|
|
||||||
|
--turn positions into pseudo 2d vectors
|
||||||
|
local pos1 = self.object:get_pos()
|
||||||
|
pos1.y = 0
|
||||||
|
|
||||||
|
local pos2 = self.following_person:get_pos()
|
||||||
|
pos2.y = 0
|
||||||
|
|
||||||
|
local new_direction = vector_direction(pos1,pos2)
|
||||||
|
local new_yaw = minetest_dir_to_yaw(new_direction)
|
||||||
|
|
||||||
|
self.object:set_yaw(new_yaw)
|
||||||
|
self.yaw = new_yaw
|
||||||
|
end
|
||||||
|
|
||||||
|
--this is used for when mobs breed
|
||||||
|
mobs.set_yaw_while_breeding = function(self, mate)
|
||||||
|
|
||||||
|
if self.object:get_properties().automatic_face_movement_dir then
|
||||||
|
self.object:set_properties{automatic_face_movement_dir = false}
|
||||||
|
end
|
||||||
|
|
||||||
|
--turn positions into pseudo 2d vectors
|
||||||
|
local pos1 = self.object:get_pos()
|
||||||
|
pos1.y = 0
|
||||||
|
|
||||||
|
local pos2 = mate:get_pos()
|
||||||
|
pos2.y = 0
|
||||||
|
|
||||||
|
local new_direction = vector_direction(pos1,pos2)
|
||||||
|
local new_yaw = minetest_dir_to_yaw(new_direction)
|
||||||
|
|
||||||
|
self.object:set_yaw(new_yaw)
|
||||||
|
self.yaw = new_yaw
|
||||||
end
|
end
|
|
@ -0,0 +1,177 @@
|
||||||
|
local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius
|
||||||
|
|
||||||
|
local vector_distance = vector.distance
|
||||||
|
|
||||||
|
--check to see if someone nearby has some tasty food
|
||||||
|
mobs.check_following = function(self) -- returns true or false
|
||||||
|
|
||||||
|
--ignore
|
||||||
|
if not self.follow then
|
||||||
|
self.following_person = nil
|
||||||
|
return(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
--hey look, this thing works for passive mobs too!
|
||||||
|
local follower = mobs.detect_closest_player_within_radius(self,true,self.view_range,self.eye_height)
|
||||||
|
|
||||||
|
--check if the follower is a player incase they log out
|
||||||
|
if follower and follower:is_player() then
|
||||||
|
local stack = follower:get_wielded_item()
|
||||||
|
--safety check
|
||||||
|
if not stack then
|
||||||
|
self.following_person = nil
|
||||||
|
return(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
local item_name = stack:get_name()
|
||||||
|
--all checks have passed, that guy has some good looking food
|
||||||
|
if item_name == self.follow then
|
||||||
|
self.following_person = follower
|
||||||
|
return(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--everything failed
|
||||||
|
self.following_person = nil
|
||||||
|
return(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
--a function which attempts to make mobs enter
|
||||||
|
--the breeding state
|
||||||
|
mobs.enter_breed_state = function(self,clicker)
|
||||||
|
|
||||||
|
--do not breed if baby
|
||||||
|
if self.baby then
|
||||||
|
return(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
--do not do anything if looking for mate or
|
||||||
|
--if cooling off from breeding
|
||||||
|
if self.breed_lookout_timer > 0 or self.breed_timer > 0 then
|
||||||
|
return(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
--if this is caught, that means something has gone
|
||||||
|
--seriously wrong
|
||||||
|
if not clicker or not clicker:is_player() then
|
||||||
|
return(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
local stack = clicker:get_wielded_item()
|
||||||
|
--safety check
|
||||||
|
if not stack then
|
||||||
|
return(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
local item_name = stack:get_name()
|
||||||
|
--all checks have passed, that guy has some good looking food
|
||||||
|
if item_name == self.follow then
|
||||||
|
if not minetest.is_creative_enabled(clicker:get_player_name()) then
|
||||||
|
stack:take_item()
|
||||||
|
clicker:set_wielded_item(stack)
|
||||||
|
end
|
||||||
|
self.breed_lookout_timer = self.breed_lookout_timer_goal
|
||||||
|
self.bred = true
|
||||||
|
return(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
--everything failed
|
||||||
|
return(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--find the closest mate in the area
|
||||||
|
mobs.look_for_mate = function(self)
|
||||||
|
|
||||||
|
local pos1 = self.object:get_pos()
|
||||||
|
pos1.y = pos1.y + self.eye_height
|
||||||
|
|
||||||
|
local mates_in_area = {}
|
||||||
|
local winner_mate = nil
|
||||||
|
local mates_detected = 0
|
||||||
|
local radius = self.view_range
|
||||||
|
|
||||||
|
--get mates in radius
|
||||||
|
for _,mate in pairs(minetest_get_objects_inside_radius(pos1, radius)) do
|
||||||
|
|
||||||
|
--look for a breeding mate
|
||||||
|
if mate and mate:get_luaentity()
|
||||||
|
and mate:get_luaentity()._cmi_is_mob
|
||||||
|
and mate:get_luaentity().name == self.name
|
||||||
|
and mate:get_luaentity().breed_lookout_timer > 0
|
||||||
|
and mate:get_luaentity() ~= self then
|
||||||
|
|
||||||
|
local pos2 = mate:get_pos()
|
||||||
|
|
||||||
|
local distance = vector_distance(pos1,pos2)
|
||||||
|
|
||||||
|
if distance <= radius then
|
||||||
|
if line_of_sight then
|
||||||
|
--must add eye height or stuff breaks randomly because of
|
||||||
|
--seethrough nodes being a blocker (like grass)
|
||||||
|
if minetest_line_of_sight(
|
||||||
|
vector_new(pos1.x, pos1.y, pos1.z),
|
||||||
|
vector_new(pos2.x, pos2.y + mate:get_properties().eye_height, pos2.z)
|
||||||
|
) then
|
||||||
|
mates_detected = mates_detected + 1
|
||||||
|
mates_in_area[mate] = distance
|
||||||
|
end
|
||||||
|
else
|
||||||
|
mates_detected = mates_detected + 1
|
||||||
|
mates_in_area[mate] = distance
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--return if there's no one near by
|
||||||
|
if mates_detected <= 0 then --handle negative numbers for some crazy error that could possibly happen
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--do a default radius max
|
||||||
|
local shortest_distance = radius + 1
|
||||||
|
|
||||||
|
--sort through mates and find the closest mate
|
||||||
|
for mate,distance in pairs(mates_in_area) do
|
||||||
|
if distance < shortest_distance then
|
||||||
|
shortest_distance = distance
|
||||||
|
winner_mate = mate
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return(winner_mate)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--make the baby grow up
|
||||||
|
mobs.baby_grow_up = function(self)
|
||||||
|
self.baby = nil
|
||||||
|
self.visual_size = self.backup_visual_size
|
||||||
|
self.collisionbox = self.backup_collisionbox
|
||||||
|
self.selectionbox = self.backup_selectionbox
|
||||||
|
self.object:set_properties(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
--makes the baby grow up faster with diminishing returns
|
||||||
|
mobs.make_baby_grow_faster = function(self,clicker)
|
||||||
|
if clicker and clicker:is_player() then
|
||||||
|
local stack = clicker:get_wielded_item()
|
||||||
|
--safety check
|
||||||
|
if not stack then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local item_name = stack:get_name()
|
||||||
|
--all checks have passed, that guy has some good looking food
|
||||||
|
if item_name == self.follow then
|
||||||
|
self.grow_up_timer = self.grow_up_timer - (self.grow_up_timer * 0.10) --take 10 percent off - diminishing returns
|
||||||
|
|
||||||
|
if not minetest.is_creative_enabled(clicker:get_player_name()) then
|
||||||
|
stack:take_item()
|
||||||
|
clicker:set_wielded_item(stack)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -9,6 +9,7 @@ local minetest_registered_nodes = minetest.registered_nodes
|
||||||
local minetest_get_connected_players = minetest.get_connected_players
|
local minetest_get_connected_players = minetest.get_connected_players
|
||||||
|
|
||||||
local vector_new = vector.new
|
local vector_new = vector.new
|
||||||
|
local vector_add = vector.add
|
||||||
local vector_multiply = vector.multiply
|
local vector_multiply = vector.multiply
|
||||||
local vector_distance = vector.distance
|
local vector_distance = vector.distance
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ mobs.detect_closest_player_within_radius = function(self, line_of_sight, radius,
|
||||||
|
|
||||||
local pos2 = player:get_pos()
|
local pos2 = player:get_pos()
|
||||||
|
|
||||||
local distance = vector.distance(pos1,pos2)
|
local distance = vector_distance(pos1,pos2)
|
||||||
|
|
||||||
if distance <= radius then
|
if distance <= radius then
|
||||||
if line_of_sight then
|
if line_of_sight then
|
||||||
|
@ -67,12 +68,12 @@ mobs.detect_closest_player_within_radius = function(self, line_of_sight, radius,
|
||||||
end
|
end
|
||||||
|
|
||||||
--do a default radius max
|
--do a default radius max
|
||||||
local shortest_disance = radius + 1
|
local shortest_distance = radius + 1
|
||||||
|
|
||||||
--sort through players and find the closest player
|
--sort through players and find the closest player
|
||||||
for player,distance in pairs(players_in_area) do
|
for player,distance in pairs(players_in_area) do
|
||||||
if distance < shortest_disance then
|
if distance < shortest_distance then
|
||||||
shortest_disance = distance
|
shortest_distance = distance
|
||||||
winner_player = player
|
winner_player = player
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -94,7 +95,7 @@ mobs.jump_check = function(self,dtime)
|
||||||
vector_multiply(dir, radius)
|
vector_multiply(dir, radius)
|
||||||
|
|
||||||
--only jump if there's a node and a non-solid node above it
|
--only jump if there's a node and a non-solid node above it
|
||||||
local test_dir = vector.add(pos,dir)
|
local test_dir = vector_add(pos,dir)
|
||||||
|
|
||||||
local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0
|
local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0
|
||||||
|
|
||||||
|
|
|
@ -119,4 +119,34 @@ mobs.tamed_effect = function(self)
|
||||||
vertical = false,
|
vertical = false,
|
||||||
texture = "heart.png",
|
texture = "heart.png",
|
||||||
})
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
--hearts when breeding
|
||||||
|
mobs.breeding_effect = function(self)
|
||||||
|
local pos = self.object:get_pos()
|
||||||
|
local yaw = self.object:get_yaw()
|
||||||
|
local collisionbox = self.object:get_properties().collisionbox
|
||||||
|
|
||||||
|
local min, max
|
||||||
|
|
||||||
|
if collisionbox then
|
||||||
|
min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]}
|
||||||
|
max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]}
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest_add_particlespawner({
|
||||||
|
amount = 2,
|
||||||
|
time = 0.0001,
|
||||||
|
minpos = vector.add(pos, min),
|
||||||
|
maxpos = vector.add(pos, max),
|
||||||
|
minvel = vector.new(-1,1,-1),
|
||||||
|
maxvel = vector.new(1,3,1),
|
||||||
|
minexptime = 0.7,
|
||||||
|
maxexptime = 1,
|
||||||
|
minsize = 1,
|
||||||
|
maxsize = 2,
|
||||||
|
collisiondetection = false,
|
||||||
|
vertical = false,
|
||||||
|
texture = "heart.png",
|
||||||
|
})
|
||||||
end
|
end
|
|
@ -6,8 +6,8 @@ local minetest_settings = minetest.settings
|
||||||
mobs.mob_staticdata = function(self)
|
mobs.mob_staticdata = function(self)
|
||||||
|
|
||||||
--despawn mechanism
|
--despawn mechanism
|
||||||
--don't despawned tamed mobs
|
--don't despawned tamed or bred mobs
|
||||||
if not self.tamed then
|
if not self.tamed and not self.bred then
|
||||||
if not mobs.check_for_player_within_area(self, 64) then
|
if not mobs.check_for_player_within_area(self, 64) then
|
||||||
--print("removing SERIALIZED!")
|
--print("removing SERIALIZED!")
|
||||||
self.object:remove()
|
self.object:remove()
|
||||||
|
@ -107,12 +107,12 @@ mobs.mob_activate = function(self, staticdata, def, dtime)
|
||||||
mesh = def.gotten_mesh
|
mesh = def.gotten_mesh
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set child objects to half size
|
-- set baby mobs to half size
|
||||||
if self.child == true then
|
if self.baby == true then
|
||||||
|
|
||||||
vis_size = {
|
vis_size = {
|
||||||
x = self.base_size.x * .5,
|
x = self.base_size.x * self.baby_size,
|
||||||
y = self.base_size.y * .5,
|
y = self.base_size.y * self.baby_size,
|
||||||
}
|
}
|
||||||
|
|
||||||
if def.child_texture then
|
if def.child_texture then
|
||||||
|
@ -120,20 +120,20 @@ mobs.mob_activate = function(self, staticdata, def, dtime)
|
||||||
end
|
end
|
||||||
|
|
||||||
colbox = {
|
colbox = {
|
||||||
self.base_colbox[1] * .5,
|
self.base_colbox[1] * self.baby_size,
|
||||||
self.base_colbox[2] * .5,
|
self.base_colbox[2] * self.baby_size,
|
||||||
self.base_colbox[3] * .5,
|
self.base_colbox[3] * self.baby_size,
|
||||||
self.base_colbox[4] * .5,
|
self.base_colbox[4] * self.baby_size,
|
||||||
self.base_colbox[5] * .5,
|
self.base_colbox[5] * self.baby_size,
|
||||||
self.base_colbox[6] * .5
|
self.base_colbox[6] * self.baby_size
|
||||||
}
|
}
|
||||||
selbox = {
|
selbox = {
|
||||||
self.base_selbox[1] * .5,
|
self.base_selbox[1] * self.baby_size,
|
||||||
self.base_selbox[2] * .5,
|
self.base_selbox[2] * self.baby_size,
|
||||||
self.base_selbox[3] * .5,
|
self.base_selbox[3] * self.baby_size,
|
||||||
self.base_selbox[4] * .5,
|
self.base_selbox[4] * self.baby_size,
|
||||||
self.base_selbox[5] * .5,
|
self.base_selbox[5] * self.baby_size,
|
||||||
self.base_selbox[6] * .5
|
self.base_selbox[6] * self.baby_size
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -65,12 +65,25 @@ mobs:register_mob("mobs_mc:chicken", {
|
||||||
run_start = 0, run_end = 40,
|
run_start = 0, run_end = 40,
|
||||||
},
|
},
|
||||||
|
|
||||||
follow = mobs_mc.follow.chicken,
|
follow = "mcl_farming:wheat_seeds",
|
||||||
|
breed_distance = 1.5,
|
||||||
|
baby_size = 0.5,
|
||||||
|
follow_distance = 2,
|
||||||
view_range = 16,
|
view_range = 16,
|
||||||
fear_height = 4,
|
fear_height = 4,
|
||||||
|
|
||||||
|
--why do chickend breed if they lay eggs??
|
||||||
on_rightclick = function(self, clicker)
|
on_rightclick = function(self, clicker)
|
||||||
if mobs:feed_tame(self, clicker, 1, true, true) then return end
|
--attempt to enter breed state
|
||||||
|
if mobs.enter_breed_state(self,clicker) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
--make baby grow faster
|
||||||
|
if self.baby then
|
||||||
|
mobs.make_baby_grow_faster(self,clicker)
|
||||||
|
return
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
do_custom = function(self, dtime)
|
do_custom = function(self, dtime)
|
||||||
|
|
|
@ -48,11 +48,17 @@ local cow_def = {
|
||||||
walk_end = 40, run_start = 0,
|
walk_end = 40, run_start = 0,
|
||||||
run_end = 40,
|
run_end = 40,
|
||||||
},
|
},
|
||||||
follow = mobs_mc.follow.cow,
|
--follow = mobs_mc.follow.cow,
|
||||||
on_rightclick = function(self, clicker)
|
on_rightclick = function(self, clicker)
|
||||||
if mobs:feed_tame(self, clicker, 1, true, true) then return end
|
|
||||||
|
|
||||||
if self.child then
|
--attempt to enter breed state
|
||||||
|
if mobs.enter_breed_state(self,clicker) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
--make baby grow faster
|
||||||
|
if self.baby then
|
||||||
|
mobs.make_baby_grow_faster(self,clicker)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -72,6 +78,9 @@ local cow_def = {
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
breed_distance = 1.5,
|
||||||
|
baby_size = 0.5,
|
||||||
|
follow_distance = 2,
|
||||||
follow = mobs_mc.items.wheat,
|
follow = mobs_mc.items.wheat,
|
||||||
view_range = 10,
|
view_range = 10,
|
||||||
fear_height = 4,
|
fear_height = 4,
|
||||||
|
@ -85,11 +94,17 @@ local mooshroom_def = table.copy(cow_def)
|
||||||
mooshroom_def.mesh = "mobs_mc_cow.b3d"
|
mooshroom_def.mesh = "mobs_mc_cow.b3d"
|
||||||
mooshroom_def.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } }
|
mooshroom_def.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } }
|
||||||
mooshroom_def.on_rightclick = function(self, clicker)
|
mooshroom_def.on_rightclick = function(self, clicker)
|
||||||
if mobs:feed_tame(self, clicker, 1, true, true) then return end
|
--attempt to enter breed state
|
||||||
|
if mobs.enter_breed_state(self,clicker) then
|
||||||
if self.child then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--make baby grow faster
|
||||||
|
if self.baby then
|
||||||
|
mobs.make_baby_grow_faster(self,clicker)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local item = clicker:get_wielded_item()
|
local item = clicker:get_wielded_item()
|
||||||
-- Use shears to get mushrooms and turn mooshroom into cow
|
-- Use shears to get mushrooms and turn mooshroom into cow
|
||||||
if item:get_name() == mobs_mc.items.shears then
|
if item:get_name() == mobs_mc.items.shears then
|
||||||
|
|
|
@ -117,7 +117,8 @@ local horse = {
|
||||||
fly = false,
|
fly = false,
|
||||||
walk_chance = 60,
|
walk_chance = 60,
|
||||||
view_range = 16,
|
view_range = 16,
|
||||||
follow = mobs_mc.follow.horse,
|
follow = "mcl_farming:wheat_item",
|
||||||
|
follow_distance = 3,
|
||||||
passive = true,
|
passive = true,
|
||||||
hp_min = 15,
|
hp_min = 15,
|
||||||
hp_max = 30,
|
hp_max = 30,
|
||||||
|
@ -217,6 +218,22 @@ local horse = {
|
||||||
local iname = item:get_name()
|
local iname = item:get_name()
|
||||||
local heal = 0
|
local heal = 0
|
||||||
|
|
||||||
|
--sneak click to breed the horse/feed it
|
||||||
|
if self.owner and self.owner == clicker:get_player_name() and clicker:get_player_control().sneak then
|
||||||
|
--attempt to enter breed state
|
||||||
|
if mobs.enter_breed_state(self,clicker) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
--make baby grow faster
|
||||||
|
if self.baby then
|
||||||
|
mobs.make_baby_grow_faster(self,clicker)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- Taming
|
-- Taming
|
||||||
self.temper = self.temper or (math.random(1,100))
|
self.temper = self.temper or (math.random(1,100))
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,9 @@ mobs:register_mob("mobs_mc:llama", {
|
||||||
walk_velocity = 1,
|
walk_velocity = 1,
|
||||||
run_velocity = 4.4,
|
run_velocity = 4.4,
|
||||||
follow_velocity = 4.4,
|
follow_velocity = 4.4,
|
||||||
|
breed_distance = 1.5,
|
||||||
|
baby_size = 0.5,
|
||||||
|
follow_distance = 2,
|
||||||
floats = 1,
|
floats = 1,
|
||||||
reach = 6,
|
reach = 6,
|
||||||
drops = {
|
drops = {
|
||||||
|
@ -92,7 +95,7 @@ mobs:register_mob("mobs_mc:llama", {
|
||||||
look_start = 78,
|
look_start = 78,
|
||||||
look_end = 108,
|
look_end = 108,
|
||||||
},
|
},
|
||||||
follow = mobs_mc.follow.llama,
|
follow = mobs_mc.items.hay_bale,
|
||||||
view_range = 16,
|
view_range = 16,
|
||||||
do_custom = function(self, dtime)
|
do_custom = function(self, dtime)
|
||||||
|
|
||||||
|
@ -135,15 +138,20 @@ mobs:register_mob("mobs_mc:llama", {
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local item = clicker:get_wielded_item()
|
if clicker:get_player_control().sneak then
|
||||||
if item:get_name() == mobs_mc.items.hay_bale then
|
--attempt to enter breed state
|
||||||
-- Breed with hay bale
|
if mobs.enter_breed_state(self,clicker) then
|
||||||
if mobs:feed_tame(self, clicker, 1, true, false) then return end
|
return
|
||||||
else
|
end
|
||||||
-- Feed with anything else
|
|
||||||
if mobs:feed_tame(self, clicker, 1, false, true) then return end
|
--make baby grow faster
|
||||||
|
if self.baby then
|
||||||
|
mobs.make_baby_grow_faster(self,clicker)
|
||||||
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Make sure tamed llama is mature and being clicked by owner only
|
-- Make sure tamed llama is mature and being clicked by owner only
|
||||||
if self.tamed and not self.child and self.owner == clicker:get_player_name() then
|
if self.tamed and not self.child and self.owner == clicker:get_player_name() then
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,9 @@ mobs:register_mob("mobs_mc:pig", {
|
||||||
walk_velocity = 1,
|
walk_velocity = 1,
|
||||||
run_velocity = 3,
|
run_velocity = 3,
|
||||||
follow_velocity = 3.4,
|
follow_velocity = 3.4,
|
||||||
|
breed_distance = 1.5,
|
||||||
|
baby_size = 0.5,
|
||||||
|
follow_distance = 2,
|
||||||
drops = {
|
drops = {
|
||||||
{name = mobs_mc.items.porkchop_raw,
|
{name = mobs_mc.items.porkchop_raw,
|
||||||
chance = 1,
|
chance = 1,
|
||||||
|
@ -50,7 +53,7 @@ mobs:register_mob("mobs_mc:pig", {
|
||||||
run_start = 0,
|
run_start = 0,
|
||||||
run_end = 40,
|
run_end = 40,
|
||||||
},
|
},
|
||||||
follow = mobs_mc.follow.pig,
|
follow = "mcl_farming:carrot_item",
|
||||||
view_range = 8,
|
view_range = 8,
|
||||||
do_custom = function(self, dtime)
|
do_custom = function(self, dtime)
|
||||||
|
|
||||||
|
@ -91,10 +94,17 @@ mobs:register_mob("mobs_mc:pig", {
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local wielditem = clicker:get_wielded_item()
|
if clicker:get_player_control().sneak then
|
||||||
-- Feed pig
|
--attempt to enter breed state
|
||||||
if wielditem:get_name() ~= mobs_mc.items.carrot_on_a_stick then
|
if mobs.enter_breed_state(self,clicker) then
|
||||||
if mobs:feed_tame(self, clicker, 1, true, true) then return end
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
--make baby grow faster
|
||||||
|
if self.baby then
|
||||||
|
mobs.make_baby_grow_faster(self,clicker)
|
||||||
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.child then
|
if self.child then
|
||||||
|
|
|
@ -63,6 +63,10 @@ mobs:register_mob("mobs_mc:sheep", {
|
||||||
xp_min = 1,
|
xp_min = 1,
|
||||||
xp_max = 3,
|
xp_max = 3,
|
||||||
skittish = true,
|
skittish = true,
|
||||||
|
breed_distance = 1.5,
|
||||||
|
baby_size = 0.5,
|
||||||
|
follow_distance = 2,
|
||||||
|
follow = mobs_mc.items.wheat,
|
||||||
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.29, 0.45},
|
collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.29, 0.45},
|
||||||
rotate = 270,
|
rotate = 270,
|
||||||
visual = "mesh",
|
visual = "mesh",
|
||||||
|
@ -100,7 +104,6 @@ mobs:register_mob("mobs_mc:sheep", {
|
||||||
walk_start = 0, walk_end = 40,
|
walk_start = 0, walk_end = 40,
|
||||||
run_start = 0, run_end = 40,
|
run_start = 0, run_end = 40,
|
||||||
},
|
},
|
||||||
follow = mobs_mc.follow.sheep,
|
|
||||||
view_range = 12,
|
view_range = 12,
|
||||||
|
|
||||||
-- Eat grass
|
-- Eat grass
|
||||||
|
@ -196,7 +199,16 @@ mobs:register_mob("mobs_mc:sheep", {
|
||||||
on_rightclick = function(self, clicker)
|
on_rightclick = function(self, clicker)
|
||||||
local item = clicker:get_wielded_item()
|
local item = clicker:get_wielded_item()
|
||||||
|
|
||||||
if mobs:feed_tame(self, clicker, 1, true, true) then return end
|
--attempt to enter breed state
|
||||||
|
if mobs.enter_breed_state(self,clicker) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
--make baby grow faster
|
||||||
|
if self.baby then
|
||||||
|
mobs.make_baby_grow_faster(self,clicker)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if item:get_name() == mobs_mc.items.shears and not self.gotten and not self.child then
|
if item:get_name() == mobs_mc.items.shears and not self.gotten and not self.child then
|
||||||
self.gotten = true
|
self.gotten = true
|
||||||
|
|
|
@ -76,6 +76,7 @@ local wolf = {
|
||||||
dog:set_yaw(yaw)
|
dog:set_yaw(yaw)
|
||||||
ent = dog:get_luaentity()
|
ent = dog:get_luaentity()
|
||||||
ent.owner = clicker:get_player_name()
|
ent.owner = clicker:get_player_name()
|
||||||
|
ent.tamed = true
|
||||||
-- cornfirm taming
|
-- cornfirm taming
|
||||||
minetest.sound_play("mobs_mc_wolf_bark", {object=dog, max_hear_distance=16}, true)
|
minetest.sound_play("mobs_mc_wolf_bark", {object=dog, max_hear_distance=16}, true)
|
||||||
-- Replace wolf
|
-- Replace wolf
|
||||||
|
@ -143,12 +144,29 @@ dog.owner_loyal = true
|
||||||
dog.follow_velocity = 3.2
|
dog.follow_velocity = 3.2
|
||||||
-- Automatically teleport dog to owner
|
-- Automatically teleport dog to owner
|
||||||
dog.do_custom = mobs_mc.make_owner_teleport_function(12)
|
dog.do_custom = mobs_mc.make_owner_teleport_function(12)
|
||||||
dog.follow = mobs_mc.follow.dog
|
|
||||||
dog.attack_animals = nil
|
dog.attack_animals = nil
|
||||||
dog.specific_attack = nil
|
dog.specific_attack = nil
|
||||||
|
dog.breed_distance = 1.5
|
||||||
|
dog.baby_size = 0.5
|
||||||
|
dog.follow_distance = 2
|
||||||
|
dog.follow = "mcl_mobitems:beef"
|
||||||
|
|
||||||
dog.on_rightclick = function(self, clicker)
|
dog.on_rightclick = function(self, clicker)
|
||||||
local item = clicker:get_wielded_item()
|
local item = clicker:get_wielded_item()
|
||||||
|
|
||||||
|
if self.owner and self.owner == clicker:get_player_name() and clicker:get_player_control().sneak then
|
||||||
|
--attempt to enter breed state
|
||||||
|
if mobs.enter_breed_state(self,clicker) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
--make baby grow faster
|
||||||
|
if self.baby then
|
||||||
|
mobs.make_baby_grow_faster(self,clicker)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if is_food(item:get_name()) then
|
if is_food(item:get_name()) then
|
||||||
-- Feed to increase health
|
-- Feed to increase health
|
||||||
local hp = self.health
|
local hp = self.health
|
||||||
|
|
Loading…
Reference in New Issue