private void InitStateMachine() { blackboard = new StateBlackboard(); blackboard.Add <bool>(BlackboardKey.DamageFlag, false); blackboard.Add <bool>(BlackboardKey.RepeatDamageFlag, false); blackboard.Add <Transform>(BlackboardKey.Transform, transform); blackboard.Add <float>(BlackboardKey.AttackRange, 0f); EnemyIdleState idleState = EnemyIdleState.Create(blackboard, animator, "Idle", 0); StateNode idleNode = new StateNode(idleState, new Condition(() => { return(true); })); SetAnimTriggerAction walkAction = new SetAnimTriggerAction(blackboard, animator, "Run"); MeleeAttackState meleeAttackState = MeleeAttackState.Create(blackboard, animator, navAgent, attackValidator.MeleeAttacks, transform, BlackboardKey.AttackRange, BlackboardKey.AnimTrigger, walkAction, 300); StateNode attackNode = new StateNode(meleeAttackState, new Condition(() => { return(target != null); })); DamageState damageState = DamageState.Create(blackboard, animator, "Damage", 500); StateNode damageNode = new StateNode(damageState, new Condition(() => { return(blackboard.Get <bool>(BlackboardKey.DamageFlag)); })); DeathState deathState = DeathState.Create(blackboard, animator, "Death", int.MaxValue); StateNode deathNode = new StateNode(deathState, new Condition(() => { return(!self.IsAlive); })); List <StateNode> nodes = new List <StateNode>(); nodes.Add(idleNode); nodes.Add(attackNode); nodes.Add(damageNode); nodes.Add(deathNode); stateMachine = new StateMachine(blackboard, nodes, idleState); }
public override void Init() { base.Init(); wanderState = new WanderState(this); shootState = new ShootState(this, enemyObj.shootRate); investigationState = new InvestigateState(this); stunnedState = new StunnedState(this); meleeAttackState = new MeleeAttackState(this); refillAmmoState = new RefifllAmmo(this); retreatState = new Retreat(this, minHealthForRetreat); qMark = Resources.Load <Sprite>("StateIcons\\what"); wanderState.AddTransition(() => { if (enemyObj.enemySight.IsPlayerInSight() && enemyObj.rifle.Ammo > 0) { Diagnostic.Instance.AddLog(enemyObj.gameObject, "See the player, shooting!"); return(true); } return(false); }, shootState); wanderState.AddTransition(() => { if (enemyObj.rifle.Ammo <= 0) { var packs = GameManager.Instance.GetAvailableAmmoPacks(); if (packs.Count > 0) { if (stateMachine.GetCurrentState() != refillAmmoState) { refillAmmoState.allPacks = packs.ToArray(); Diagnostic.Instance.AddLog(enemyObj.gameObject, "No ammo, got nothing to do, going to get some"); return(true); } } } return(false); }, refillAmmoState); wanderState.AddTransition(() => { if (enemyObj.health.GetHealth() < minHealthForRetreat) { var packs = GameManager.Instance.GetAvailableHealthPacks(); if (packs.Count > 0) { if (stateMachine.GetCurrentState() != retreatState) { retreatState.allPacks = packs.ToArray(); Diagnostic.Instance.AddLog(enemyObj.gameObject, "Low health, got nothing to do, going to get some"); return(true); } } } return(false); }, retreatState); wanderState.AddTransition(() => { if (enemyObj.rifle.Ammo <= 0) { var packs = GameManager.Instance.GetAvailableAmmoPacks(); if (packs.Count > 0) { if (stateMachine.GetCurrentState() != refillAmmoState) { Diagnostic.Instance.AddLog(enemyObj.gameObject, "No ammo, got nothing to do, going to get some"); return(true); } } } return(false); }, refillAmmoState); wanderState.AddTransition(() => { if (enemyObj.enemySight.IsPlayerInSight() && enemyObj.rifle.Ammo <= 0) { Diagnostic.Instance.AddLog(enemyObj.gameObject, "See the player, no ammo, will attack with hands!"); return(true); } return(false); }, meleeAttackState); refillAmmoState.AddTransition(() => { if (enemyObj.rifle.Ammo > 0) { if (refillAmmoState.playerLastKnowsPosition == null) { Diagnostic.Instance.AddLog(enemyObj.gameObject, "Go ammo, don't know where player is, will wander around"); return(true); } } return(false); }, wanderState); refillAmmoState.AddTransition(() => { if (enemyObj.enemySight.IsPlayerInSight()) { Diagnostic.Instance.AddLog(enemyObj.gameObject, "Saw player, no time for refill ammo, attack!"); return(true); } return(false); }, meleeAttackState); retreatState.AddTransition(() => { if (enemyObj.enemySight.IsPlayerInSight()) { Diagnostic.Instance.AddLog(enemyObj.gameObject, "Saw player, no time for get healthpack, attack!"); return(true); } return(false); }, shootState); retreatState.AddTransition(() => { //If the health was restored OR health is low but no packs available, go back wandering if (enemyObj.health.GetHealth() > minHealthForRetreat || (enemyObj.health.GetHealth() <= minHealthForRetreat && GameManager.Instance.GetAvailableHealthPacks().Count == 0)) { Diagnostic.Instance.AddLog(enemyObj.gameObject, "Feeling better, going to stroll around..."); return(true); } return(false); }, wanderState); shootState.AddTransition(() => { if (!enemyObj.enemySight.IsPlayerInSight()) { investigationState.waitBeforeGoingToPoint = 0; investigationState.investigationPoint = Player.Instance.transform.position; shootTimer = 15.0f; Diagnostic.Instance.AddLog(enemyObj.gameObject, "Lost sight of player, going to check last known psition (and keep shooting, why not)"); return(true); } return(false); }, investigationState); shootState.AddTransition(() => { return(enemyObj.rifle.Ammo <= 0); }, meleeAttackState); meleeAttackState.AddTransition(() => { if (meleeAttackState.playerLastKnownPosition != null) { investigationState.investigationPoint = meleeAttackState.playerLastKnownPosition.Value; return(true); } return(false); }, investigationState); investigationState.AddTransition(() => { if (enemyObj.enemySight.IsPlayerInSight()) { Diagnostic.Instance.AddLog(enemyObj.gameObject, "See the player, shooting!"); return(true); } return(false); }, shootState); investigationState.AddTransition(() => { return(investigationState.done); }, wanderState); stunnedState.AddTransition(() => { if (!stunnedState.isStunned) { investigationState.investigationPoint = enemyObj.transform.position; return(true); } return(false); }, investigationState); //Beserk will respond to alarm Enemy.OnAlarmSent += GoInsestigateSOS; stateMachine.SetState(wanderState); }
private void Start() { attackState = new MeleeAttackState(this); }