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; }); }
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); }); }
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); }); }