From ed9d629b99a9f873cebfa8e45239271a81a8025c Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 23 Apr 2021 21:59:42 -0400 Subject: [PATCH] Add in mob following for cows --- mods/ENTITIES/mcl_mobs/api/api.lua | 9 ++-- .../mcl_mobs/api/mob_functions/ai.lua | 49 +++++++++++++++++-- .../mcl_mobs/api/mob_functions/animation.lua | 22 +++++++++ .../mcl_mobs/api/mob_functions/breeding.lua | 33 +++++++++++++ .../mcl_mobs/api/mob_functions/set_up.lua | 2 +- mods/ENTITIES/mobs_mc/cow+mooshroom.lua | 14 +++--- 6 files changed, 114 insertions(+), 15 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index f748a09355..af2ce1d7c6 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -265,8 +265,6 @@ function mobs:register_mob(name, def) env_damage_timer = 0, tamed = false, pause_timer = 0, - horny = false, - hornytimer = 0, gotten = false, health = 0, reach = def.reach or 3, @@ -298,7 +296,6 @@ function mobs:register_mob(name, def) owner_loyal = def.owner_loyal, facing_fence = false, - _cmi_is_mob = true, pushable = def.pushable or true, @@ -331,6 +328,12 @@ function mobs:register_mob(name, def) skittish = def.skittish, lifetimer_reset = 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 -- MCL2 extensions diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index ff1b72df6b..8a4add6568 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -6,6 +6,7 @@ local math_round = math.round local vector_multiply = vector.multiply local vector_add = vector.add local vector_new = vector.new +local vector_distance = vector.distance local minetest_yaw_to_dir = minetest.yaw_to_dir 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) - --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 --only run away @@ -76,18 +78,27 @@ local land_state_switch = function(self, dtime) if self.run_timer > 0 then return end - --continue 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 if self.hostile and self.attacking then self.state = "attack" return end - - + --if finally reached here then do random wander if self.state_timer <= 0 then self.state_timer = math.random(4,10) + math.random() 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 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 collisionbox = self.object:get_properties().collisionbox --get the center of the mob @@ -145,6 +166,24 @@ local land_state_execution = function(self,dtime) 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 self.walk_timer = self.walk_timer - dtime @@ -697,7 +736,7 @@ mobs.mob_step = function(self, dtime) end --despawn mechanism - --don't despawned tamed mobs + --don't despawned tamed or bred mobs if not self.tamed and not self.bred then self.lifetimer = self.lifetimer - dtime if self.lifetimer <= 0 then diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua index fbf140034c..809eacef5d 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua @@ -213,4 +213,26 @@ mobs.handle_explosion_animation = function(self) visual_size_modified.y = visual_size_modified.y * explosion_timer_adjust 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 \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/breeding.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/breeding.lua index e69de29bb2..975495f046 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/breeding.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/breeding.lua @@ -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 \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua index f4a050da21..864b888e81 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua @@ -6,7 +6,7 @@ local minetest_settings = minetest.settings mobs.mob_staticdata = function(self) --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 mobs.check_for_player_within_area(self, 64) then --print("removing SERIALIZED!") diff --git a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua index dfc98aad4c..6dbb594f02 100644 --- a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua +++ b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua @@ -50,13 +50,13 @@ local cow_def = { }, follow = mobs_mc.follow.cow, on_rightclick = function(self, clicker) - if mobs:feed_tame(self, clicker, 1, true, true) then - return - end + --if mobs:feed_tame(self, clicker, 1, true, true) then + --return + --end - if self.child then - return - end + --if self.child then + -- return + --end local item = clicker:get_wielded_item() if item:get_name() == mobs_mc.items.bucket and clicker:get_inventory() then @@ -74,6 +74,8 @@ local cow_def = { return end end, + breedable = true, + follow_distance = 2, follow = mobs_mc.items.wheat, view_range = 10, fear_height = 4,