Пример #1
0
        public void Update(MobAIBase aiBase, float dt)
        {
            if ((m_currentSearchTime += dt) > MaxSearchTime)
            {
                m_currentSearchTime = 0f;
                aiBase.Brain.Fire(Trigger.Timeout);
            }

            if (aiBase.Brain.IsInState(State.MoveToContainer))
            {
                //Common.Dbgl($"State MoveToContainer: {KnownContainers.Peek().name}");
                if (KnownContainers.Peek() == null)
                {
                    aiBase.StopMoving();
                    KnownContainers.Pop();
                    aiBase.Brain.Fire(Trigger.Failed);
                    //Common.Dbgl("Container = null");
                    return;
                }
                aiBase.MoveAndAvoidFire(KnownContainers.Peek().transform.position, dt, 0.5f);
                if (Vector3.Distance(aiBase.Instance.transform.position, KnownContainers.Peek().transform.position) < 2)
                {
                    aiBase.StopMoving();
                    aiBase.Brain.Fire(Trigger.ContainerIsClose);
                    //Debug.Log($"{KnownContainers.Peek().name} is close");
                }
                return;
            }

            if (aiBase.Brain.IsInState(State.MoveToGroundItem))
            {
                if (m_groundItem == null || m_groundItem?.GetComponent <ZNetView>()?.IsValid() != true)
                {
                    m_groundItem = null;
                    aiBase.StopMoving();
                    aiBase.Brain.Fire(Trigger.Failed);
                    //Debug.Log("GroundItem = null");
                    return;
                }
                aiBase.MoveAndAvoidFire(m_groundItem.transform.position, dt, 0.5f);
                if (Vector3.Distance(aiBase.Instance.transform.position, m_groundItem.transform.position) < 1.5)
                {
                    aiBase.StopMoving();
                    aiBase.Brain.Fire(Trigger.GroundItemIsClose);
                    //Debug.Log("GroundItem is close");
                }
                return;
            }

            if (aiBase.Brain.IsInState(State.OpenContainer))
            {
                if ((m_openChestTimer += dt) > OpenChestDelay)
                {
                    //Debug.Log("Open Container");
                    aiBase.Brain.Fire(Trigger.ContainerOpened);
                }
            }
        }
Пример #2
0
 public void Update(MobAIBase instance, float dt)
 {
     m_hungryTimer += dt;
     if (instance.Brain.State == State.Hungry)
     {
         Common.Invoke <BaseAI>(instance.Instance, "RandomMovement", dt, LastKnownFoodPosition);
         instance.Brain.Fire(UpdateTrigger, dt);
     }
 }
Пример #3
0
        public static bool TurnToFacePosition(MobAIBase mob, Vector3 position)
        {
            bool isLookingAtTarget = (bool)Invoke <MonsterAI>(mob.Instance, "IsLookingAt", position, 10f);

            if (isLookingAtTarget)
            {
                return(true);
            }

            Invoke <MonsterAI>(mob.Instance, "LookAt", position);
            return(false);
        }
Пример #4
0
        public void Configure(MobAIBase aiBase, StateMachine <string, string> brain, string parentState)
        {
            m_aiBase          = aiBase;
            m_foodsearchtimer = 0f;
            if (LastKnownFoodPosition == Vector3.zero)
            {
                LastKnownFoodPosition = aiBase.Character.transform.position;
            }

            UpdateTrigger      = brain.SetTriggerParameters <float>(Trigger.Update);
            LookForItemTrigger = brain.SetTriggerParameters <IEnumerable <ItemDrop.ItemData>, string, string>(Trigger.ItemFound);

            brain.Configure(State.Hungry)
            .SubstateOf(parentState)
            .PermitIf(UpdateTrigger, State.SearchForFood, (dt) => (m_foodsearchtimer += dt) > 10)
            .OnEntry(t =>
            {
                aiBase.StopMoving();
                aiBase.UpdateAiStatus("Is hungry, no work a do");
            })
            .OnExit(t =>
            {
                Debug.LogWarning("Exiting EatingBehaviour");
            });

            brain.Configure(State.SearchForFood)
            .SubstateOf(State.Hungry)
            .PermitDynamic(LookForItemTrigger.Trigger, () => SearchForItemsState)
            .OnEntry(t =>
            {
                m_foodsearchtimer = 0f;
                brain.Fire(LookForItemTrigger, (aiBase.Instance as MonsterAI).m_consumeItems.Select(i => i.m_itemData), State.HaveFoodItem, State.HaveNoFoodItem);
            });

            brain.Configure(State.HaveFoodItem)
            .SubstateOf(State.Hungry)
            .PermitDynamic(Trigger.ConsumeItem, () => SuccessState)
            .OnEntry(t =>
            {
                aiBase.UpdateAiStatus("*burps*");
                (aiBase.Instance as MonsterAI).m_onConsumedItem((aiBase.Instance as MonsterAI).m_consumeItems.FirstOrDefault());
                (aiBase.Instance.GetComponent <Character>() as Humanoid).m_consumeItemEffects.Create(aiBase.Instance.transform.position, Quaternion.identity);
                var animator = aiBase.Instance.GetType().GetField("m_animator", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(aiBase.Instance) as ZSyncAnimation;
                animator.SetTrigger("consume");
                float consumeHeal = aiBase.Character.GetMaxHealth() * HealPercentageOnConsume;
                Common.Dbgl($"consumeHeal:{consumeHeal}");

                if (consumeHeal > 0f)
                {
                    aiBase.Instance.GetComponent <Character>().Heal(consumeHeal);
                }
                m_hungryTimer         = 0f;
                LastKnownFoodPosition = aiBase.Character.transform.position;
                Debug.LogWarning($"SuccessState:{SuccessState}");
                brain.Fire(Trigger.ConsumeItem);
            })
            .OnExit(t =>
            {
                Debug.LogWarning($"Exiting HaveFoodItem, Trigger:{t.Trigger}");
            });

            brain.Configure(State.HaveNoFoodItem)
            .SubstateOf(State.Hungry)
            .PermitIf(Trigger.ItemNotFound, State.Hungry)
            .OnEntry(t =>
            {
                brain.Fire(Trigger.ItemNotFound);
            });
        }
Пример #5
0
        public void Configure(MobAIBase aiBase, StateMachine <string, string> brain, string parentState)
        {
            m_aiBase = aiBase;
            brain.Configure(State.Main)
            .InitialTransition(State.IdentifyEnemy)
            .PermitDynamic(Trigger.Flee, () => FailState)
            .Permit(Trigger.TargetLost, State.IdentifyEnemy)
            .SubstateOf(parentState)
            .OnEntry(t =>
            {
                m_aiBase.UpdateAiStatus("Entered fighting behaviour");
                m_startPosition        = aiBase.Instance.transform.position;
                m_viewRange            = m_awarenessLevel * 5f;
                m_circleTargetDistance = m_mobilityLevel * 2 - m_agressionLevel;
                m_searchTargetMovement = m_mobilityLevel;
            })
            .OnExit(t =>
            {
                aiBase.StopMoving();
                aiBase.TargetCreature = null;
            });

            brain.Configure(State.IdentifyEnemy)
            .SubstateOf(State.Main)
            .Permit(Trigger.FoundTarget, State.SelectWeapon)
            .Permit(Trigger.NoTarget, State.DoneFighting)
            .OnEntry(t =>
            {
                //Debug.Log("IdentifyEnemy-Enter");
                m_searchTimer = m_agressionLevel * 2;
                if (aiBase.Attacker != null && aiBase.Instance.CanSenseTarget(aiBase.Attacker))
                {
                    aiBase.TargetCreature = aiBase.Attacker;
                    aiBase.Brain.Fire(Trigger.FoundTarget);
                    return;
                }
            });

            brain.Configure(State.SelectWeapon)
            .SubstateOf(State.Main)
            .Permit(Trigger.WeaponSelected, State.TrackingEnemy)
            .PermitDynamic(Trigger.Failed, () => FailState)
            .OnEntry(t =>
            {
                //Debug.Log("SelectWeapon-Enter");
                m_weapon = (ItemDrop.ItemData)Common.Invoke <MonsterAI>(aiBase.Instance, "SelectBestAttack", (aiBase.Character as Humanoid), 1.0f);
                if (m_weapon == null)
                {
                    //Debug.Log("SelectWeapon-Fail");
                    brain.Fire(Trigger.Failed);
                }
                else
                {
                    brain.Fire(Trigger.WeaponSelected);
                }
            });


            brain.Configure(State.TrackingEnemy)
            .SubstateOf(State.Main)
            .Permit(Trigger.Attack, State.EngagingEnemy)
            .Permit(Trigger.NoTarget, State.IdentifyEnemy)
            .OnEntry(t =>
            {
                //Debug.Log("TrackingEnemy-Enter");
                m_searchTimer = m_agressionLevel * 2;
            });

            brain.Configure(State.EngagingEnemy)
            .SubstateOf(State.Main)
            .Permit(Trigger.Attack, State.TrackingEnemy)
            .Permit(Trigger.NoTarget, State.IdentifyEnemy)
            .Permit(Trigger.Reposition, State.CirclingEnemy)
            .OnEntry(t =>
            {
                m_circleTimer = m_agressionLevel;
            });

            brain.Configure(State.CirclingEnemy)
            .Permit(Trigger.Attack, State.TrackingEnemy)
            .SubstateOf(State.Main)
            .OnEntry(t =>
            {
                m_circleTimer = 30f / m_agressionLevel;
                aiBase.Character.Heal(aiBase.Character.GetMaxHealth() / 50);
            });


            brain.Configure(State.DoneFighting)
            .SubstateOf(State.Main)
            .PermitDynamic(Trigger.Done, () => SuccessState)
            .OnEntry(t =>
            {
                m_aiBase.UpdateAiStatus("Done fighting.");
                aiBase.Character.Heal(aiBase.Character.GetMaxHealth() / 10);
            })
            .OnExit(t =>
            {
                aiBase.Attacker      = null;
                aiBase.TimeSinceHurt = 20;
            });
        }
Пример #6
0
 public bool IsBelowHealthThreshold(MobAIBase aiBase)
 {
     return(aiBase.Character.GetHealthPercentage() < 1 - m_agressionLevel * 0.08);
 }
Пример #7
0
        public void Update(MobAIBase aiBase, float dt)
        {
            if (IsBelowHealthThreshold(aiBase))
            {
                aiBase.Brain.Fire(Trigger.Flee);
                return;
            }

            if (aiBase.Brain.IsInState(State.IdentifyEnemy))
            {
                m_searchTimer -= dt;
                Common.Invoke <MonsterAI>(aiBase.Instance, "RandomMovementArroundPoint", dt, m_startPosition, m_circleTargetDistance, true);
                if (Vector3.Distance(m_startPosition, aiBase.Character.transform.position) > m_viewRange - 5)
                {
                    return;
                }
                aiBase.TargetCreature = BaseAI.FindClosestEnemy(aiBase.Character, m_startPosition, m_viewRange);
                if (aiBase.TargetCreature != null && Vector3.Distance(m_startPosition, aiBase.TargetCreature.transform.position) < m_viewRange)
                {
                    Common.Invoke <MonsterAI>(aiBase.Instance, "LookAt", aiBase.TargetCreature.transform.position);
                    //Debug.Log("IdentifyEnemy-FoundTarget");
                    aiBase.Brain.Fire(Trigger.FoundTarget);
                    return;
                }
                if (m_searchTimer <= 0)
                {
                    //Debug.Log("IdentifyEnemy-NoTarget");
                    aiBase.StopMoving();
                    aiBase.Brain.Fire(Trigger.NoTarget);
                }
                return;
            }

            if (aiBase.TargetCreature == null)
            {
                aiBase.Attacker = null;
                aiBase.Brain.Fire(Trigger.TargetLost);
                //Debug.Log("TargetLost");
                return;
            }

            if (aiBase.Brain.IsInState(State.TrackingEnemy))
            {
                m_searchTimer -= dt;
                if (aiBase.Attacker != null && aiBase.TargetCreature != aiBase.Attacker && aiBase.Instance.CanSenseTarget(aiBase.Attacker))
                {
                    aiBase.TargetCreature = aiBase.Attacker;
                    ////Debug.Log("TrackingEnemy-Switch target to Attacker");
                }
                Common.Invoke <MonsterAI>(aiBase.Instance, "LookAt", aiBase.TargetCreature.transform.position);
                if (Vector3.Distance(m_startPosition, aiBase.Character.transform.position) > m_viewRange && (aiBase.TargetCreature != aiBase.Attacker || m_agressionLevel < 5))
                {
                    //Debug.Log("TrackingEnemy-NoTarget(lost track)");
                    aiBase.TargetCreature = null;
                    aiBase.Attacker       = null;
                    aiBase.StopMoving();
                    aiBase.Brain.Fire(Trigger.NoTarget);
                    return;
                }
                //Debug.Log("TrackingEnemy-MoveToTarget");
                if (aiBase.MoveAndAvoidFire(aiBase.TargetCreature.transform.position, dt, Math.Max(m_weapon.m_shared.m_aiAttackRange - 0.5f, 1.0f), true))
                {
                    aiBase.StopMoving();
                    //Debug.Log("TrackingEnemy-Attack");
                    aiBase.Brain.Fire(Trigger.Attack);
                    return;
                }
                if (m_searchTimer <= 0)
                {
                    //Debug.Log("TrackingEnemy-NoTarget(timeout)");
                    aiBase.TargetCreature = null;
                    aiBase.Attacker       = null;
                    aiBase.StopMoving();
                    aiBase.Brain.Fire(Trigger.NoTarget);
                }
                //Debug.Log("TrackingEnemy-End");
                return;
            }

            if (aiBase.Brain.IsInState(State.EngagingEnemy))
            {
                m_circleTimer -= dt;
                bool isLookingAtTarget = (bool)Common.Invoke <MonsterAI>(aiBase.Instance, "IsLookingAt", aiBase.TargetCreature.transform.position, 10f);
                bool isCloseToTarget   = Vector3.Distance(aiBase.Instance.transform.position, aiBase.TargetCreature.transform.position) < m_weapon.m_shared.m_aiAttackRange;
                if (!isCloseToTarget)
                {
                    //Debug.Log("EngagingEnemy-Attack");
                    aiBase.Brain.Fire(Trigger.Attack);
                    return;
                }
                if (!isLookingAtTarget)
                {
                    Common.Invoke <MonsterAI>(aiBase.Instance, "LookAt", aiBase.TargetCreature.transform.position);
                    return;
                }
                if (m_circleTimer <= 0)
                {
                    //Debug.Log("EngagingEnemy-Reposition");
                    aiBase.Brain.Fire(Trigger.Reposition);
                    return;
                }
                Common.Invoke <MonsterAI>(aiBase.Instance, "DoAttack", aiBase.TargetCreature, false);
                //Debug.Log("EngagingEnemy-DoAttack");
                return;
            }

            if (aiBase.Brain.IsInState(State.CirclingEnemy))
            {
                m_circleTimer -= dt;
                Common.Invoke <MonsterAI>(aiBase.Instance, "RandomMovementArroundPoint", dt, aiBase.TargetCreature.transform.position, m_circleTargetDistance, true);
                if (m_circleTimer <= 0)
                {
                    //Debug.Log("CirclingEnemy-Attack");
                    aiBase.Brain.Fire(Trigger.Attack);
                    return;
                }
            }

            if (aiBase.Brain.IsInState(State.DoneFighting))
            {
                aiBase.MoveAndAvoidFire(m_startPosition, dt, 0.5f, false);
                if (Vector3.Distance(m_startPosition, aiBase.Character.transform.position) < 1f)
                {
                    //Debug.Log("DoneFighting-Done");
                    aiBase.Brain.Fire(Trigger.Done);
                }
                return;
            }
        }
Пример #8
0
 public abstract void GotShoutedAtBy(MobAIBase mob);
Пример #9
0
        public void Configure(MobAIBase aiBase, StateMachine <string, string> brain, string parentState)
        {
            m_aiBase = aiBase;
            FoundGroundItemTrigger = brain.SetTriggerParameters <ItemDrop>(Trigger.FoundGroundItem);
            m_searchRadius         = aiBase.Awareness * 5;



            brain.Configure(State.Main)
            .InitialTransition(State.SearchItemsOnGround)
            .SubstateOf(parentState)
            .PermitDynamic(Trigger.Timeout, () => FailState)
            .OnEntry(t =>
            {
                //Debug.Log("Entered SearchForItemsBehaviour");
            })
            .OnExit(t =>
            {
                KnownContainers.Peek()?.SetInUse(inUse: false);
            });

            brain.Configure(State.SearchItemsOnGround)
            .SubstateOf(State.Main)
            .Permit(FoundGroundItemTrigger.Trigger, State.MoveToGroundItem)
            .Permit(Trigger.Failed, State.SearchForRandomContainer)
            .OnEntry(t =>
            {
                ItemDrop groundItem = Common.GetNearbyItem(m_aiBase.Instance, Items, m_searchRadius);
                if (groundItem != null)
                {
                    m_aiBase.UpdateAiStatus($"Look, there is a {groundItem.m_itemData.m_shared.m_name} on da grund");
                    brain.Fire(FoundGroundItemTrigger, groundItem);
                    return;
                }
                m_aiBase.UpdateAiStatus($"I seen nottin on da ground.");
                brain.Fire(Trigger.Failed);
            });

            brain.Configure(State.SearchForRandomContainer)
            .SubstateOf(State.Main)
            .Permit(Trigger.ContainerFound, State.MoveToContainer)
            .PermitDynamic(Trigger.ContainerNotFound, () => FailState)
            .PermitDynamic(Trigger.Failed, () => FailState)
            .OnEntry(t =>
            {
                if (KnownContainers.Any())
                {
                    var matchingContainer = KnownContainers.Where(c => c.GetInventory().GetAllItems().Any(i => Items.Any(it => i.m_shared.m_name == it.m_shared.m_name))).RandomOrDefault();
                    if (matchingContainer != null)
                    {
                        KnownContainers.Remove(matchingContainer);
                        KnownContainers.Push(matchingContainer);
                        m_aiBase.UpdateAiStatus($"I seen this in that a bin");
                        brain.Fire(Trigger.ContainerFound);
                        return;
                    }
                }

                Container nearbyChest = Common.FindRandomNearbyContainer(m_aiBase.Instance, KnownContainers, AcceptedContainerNames, m_searchRadius);
                if (nearbyChest != null)
                {
                    KnownContainers.Push(nearbyChest);
                    m_aiBase.UpdateAiStatus($"Look a bin!");
                    m_aiBase.Brain.Fire(Trigger.ContainerFound);
                }
                else
                {
                    m_aiBase.UpdateAiStatus($"Me give up, nottin found!");
                    KnownContainers.Clear();
                    m_aiBase.Brain.Fire(Trigger.ContainerNotFound);
                }
            });

            brain.Configure(State.MoveToGroundItem)
            .SubstateOf(State.Main)
            .Permit(Trigger.GroundItemIsClose, State.PickUpItemFromGround)
            .Permit(Trigger.Failed, State.SearchItemsOnGround)
            .OnEntry(t =>
            {
                m_groundItem = t.Parameters[0] as ItemDrop;
                if (m_groundItem == null || Common.GetNView(m_groundItem)?.IsValid() != true)
                {
                    brain.Fire(Trigger.Failed);
                    return;
                }
                m_aiBase.UpdateAiStatus($"Heading to {m_groundItem.m_itemData.m_shared.m_name}");
            });

            brain.Configure(State.PickUpItemFromGround)
            .SubstateOf(State.Main)
            .PermitDynamic(Trigger.ItemFound, () => SuccessState)
            .Permit(Trigger.Failed, State.SearchItemsOnGround)
            .OnEntry(t =>
            {
                FoundItem = m_groundItem.m_itemData;
                if (m_groundItem == null || Common.GetNView(m_groundItem)?.IsValid() != true)
                {
                    brain.Fire(Trigger.Failed);
                    return;
                }
                m_aiBase.UpdateAiStatus($"Got a {FoundItem.m_shared.m_name} from the ground");
                if (m_groundItem.RemoveOne())
                {
                    brain.Fire(Trigger.ItemFound);
                }
                else
                {
                    brain.Fire(Trigger.Failed);
                }
            });

            brain.Configure(State.MoveToContainer)
            .SubstateOf(State.Main)
            .Permit(Trigger.ContainerIsClose, State.OpenContainer)
            .Permit(Trigger.Failed, State.SearchItemsOnGround)
            .PermitDynamic(Trigger.ContainerNotFound, () => FailState)
            .OnEntry(t =>
            {
                m_aiBase.UpdateAiStatus($"Heading to that a bin");
            });

            brain.Configure(State.OpenContainer)
            .SubstateOf(State.Main)
            .Permit(Trigger.ContainerOpened, State.SearchForItem)
            .Permit(Trigger.Failed, State.SearchItemsOnGround)
            .OnEntry(t =>
            {
                if (KnownContainers.Peek() == null || KnownContainers.Peek().IsInUse())
                {
                    KnownContainers.Pop();
                    brain.Fire(Trigger.Failed);
                }
                else
                {
                    KnownContainers.Peek().SetInUse(inUse: true);
                    m_openChestTimer = 0f;
                }
            });

            brain.Configure(State.SearchForItem)
            .SubstateOf(State.Main)
            .PermitDynamic(Trigger.ItemFound, () => SuccessState)
            .Permit(Trigger.Failed, State.SearchItemsOnGround)
            .OnEntry(t =>
            {
                if (KnownContainers.Peek() == null)
                {
                    brain.Fire(Trigger.Failed);
                    return;
                }
                FoundItem = KnownContainers.Peek().GetInventory().GetAllItems().Where(i => Items.Any(it => i.m_shared.m_name == it.m_shared.m_name)).RandomOrDefault();
                if (FoundItem != null)
                {
                    m_aiBase.UpdateAiStatus($"Found {FoundItem.m_shared.m_name} in this a bin!");
                    KnownContainers.Peek().GetInventory().RemoveItem(FoundItem, 1);
                    Common.Invoke <Container>(KnownContainers.Peek(), "Save");
                    Common.Invoke <Inventory>(KnownContainers.Peek().GetInventory(), "Changed");

                    brain.Fire(Trigger.ItemFound);
                }
                else
                {
                    m_aiBase.UpdateAiStatus($"Nottin in this a bin..");
                    brain.Fire(Trigger.Failed);
                }
            })
            .OnExit(t =>
            {
                KnownContainers.Peek().SetInUse(inUse: false);
            });
        }