Add in mob following for cows

This commit is contained in:
jordan4ibanez 2021-04-23 21:59:42 -04:00
parent fcfd6b9d19
commit ed9d629b99
6 changed files with 114 additions and 15 deletions

View File

@ -265,8 +265,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,
@ -298,7 +296,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,
@ -331,6 +328,12 @@ 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
breedable = def.breedable,
breed_timer = 0,
breed_cooloff_timer = 5*60, -- 5 minutes
bred = false,
follow_distance = def.follow_distance or 2,
--end j4i stuff --end j4i stuff
-- MCL2 extensions -- MCL2 extensions

View File

@ -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,27 @@ 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 following
if mobs.check_following(self) 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)]
@ -103,6 +114,16 @@ local land_state_execution = function(self,dtime)
return return
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 = nil
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
--get the center of the mob --get the center of the mob
@ -145,6 +166,24 @@ local land_state_execution = function(self,dtime)
mobs.lock_yaw(self) mobs.lock_yaw(self)
elseif self.state == "follow" then
mobs.set_yaw_while_following(self)
local distance_from_follow_person = vector_distance(self.object:get_pos(), self.following_person:get_pos())
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
self.walk_timer = self.walk_timer - dtime self.walk_timer = self.walk_timer - dtime
@ -697,7 +736,7 @@ 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 and not self.bred 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

View File

@ -213,4 +213,26 @@ 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 end

View File

@ -0,0 +1,33 @@
--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

View File

@ -6,7 +6,7 @@ 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 and not self.bred 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!")

View File

@ -50,13 +50,13 @@ local cow_def = {
}, },
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 --if mobs:feed_tame(self, clicker, 1, true, true) then
return --return
end --end
if self.child then --if self.child then
return -- return
end --end
local item = clicker:get_wielded_item() local item = clicker:get_wielded_item()
if item:get_name() == mobs_mc.items.bucket and clicker:get_inventory() then if item:get_name() == mobs_mc.items.bucket and clicker:get_inventory() then
@ -74,6 +74,8 @@ local cow_def = {
return return
end end
end, end,
breedable = true,
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,