Esempio n. 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);
                }
            }
        }
Esempio n. 2
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);
            });
        }
Esempio n. 3
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;
            });
        }
Esempio n. 4
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;
            }
        }