Esempio n. 1
0
    private IEnumerator SendGoblinInCaveRoutine(Goblin g)
    {
        CaveView.CloseCave();

        //Goblin walk there
        g.MoveTo(transform.position);

        //Wait for resolution
        yield return(new WaitForSeconds(2));

        //turn off goblin
        g.gameObject.SetActive(false);

        //Wait for resolution
        yield return(new WaitForSeconds(2));

        //Arrive back with treasure or Remove goblin
        if (Random.Range(0, g.SMA.GetStatMax()) >= Difficulty)
        {
            g.Xp += 10;
            g.Team.OnTreasureFound.Invoke(Prize);
            PopUpText.ShowText(g.name + " found many goblin treasures in Cave!");
            g.gameObject.SetActive(true);
            g.ChangeState(Character.CharacterState.Idling, true);

            Explored = true;
        }
        else
        {
            PopUpText.ShowText(g + " did not return from exploring the cave!");
            g.Health = 0;
            g.Team.Members.Remove(g);
        }
    }
Esempio n. 2
0
    //TODO: move to general POI method
    private IEnumerator Spawning()
    {
        if (HasBeenAttacked)
        {
            yield break;
        }

        HasBeenAttacked = true;

        yield return(new WaitForSeconds(0.5f));

        var spawn = new List <Character>();

        for (int i = 0; i < EnemiesOnAttack; i++)
        {
            var z = MapGenerator.GenerateCharacter(SpawnEnemies[Random.Range(0, SpawnEnemies.Length)], InArea, NpcHolder.Instance.transform, true).GetComponent <Character>();

            z.ChangeState(Character.CharacterState.Attacking);

            spawn.Add(z);

            yield return(new WaitForSeconds(Random.Range(0, 1.5f)));
        }

        if (WinCondition)
        {
            yield return(new WaitUntil(() => spawn.All(s => !s.Alive())));

            Debug.Log("PLAYER HAS WON");

            PopUpText.ShowText("The goblins have found a new home!");
            SoundController.PlayStinger(SoundBank.Stinger.GameWin);
        }
    }
Esempio n. 3
0
    private void Die(Character self)
    {
        //TODO: remove listeners
        OnDamage.RemoveAllListeners();

        if (this as Goblin)
        {
            (this as Goblin).particles.Stop();
        }

        (this as Goblin)?.Speak(SoundBank.GoblinSound.Death);

        if (MovementAudio)
        {
            MovementAudio.Stop();
        }

        State = CharacterState.Dead;

        HealtBar.gameObject.SetActive(false);

        if (tag == "Player")
        {
            PopUpText.ShowText(name + " is dead");
        }

        //LOOT CREATIONS
        var loot = gameObject.AddComponent <Lootable>();

        loot.ContainsLoot = false;
        if (CharacterRace != Race.Goblin)
        {
            loot.ContainsFood = true;

            loot.Food = CharacterRace + " " + NameGenerator.GetFoodName();
        }
        var removeEquip = Equipped.Values.Where(e => e).ToArray();

        foreach (var eq in removeEquip)
        {
            RemoveEquipment(eq);

            loot.EquipmentLoot.Add(eq);

            eq.transform.parent = loot.transform.parent;
        }

        InArea.Lootables.Add(loot);

        //TODO: check if this create problems:
        navMeshAgent.enabled = false;
    }
Esempio n. 4
0
    private void NextLevel()
    {
        //a sound
        SoundController.PlayLevelup();

        PopUpText.ShowText(name + " has gained a new level!");

        //TODO: health should be handled differently than other stuff
        HEA.LevelUp();

        if (CurrentLevel == 2)
        {
            WaitingOnClassSelection = true;
        }

        GoblinUIList.UpdateGoblinList();
    }
Esempio n. 5
0
    private void SelectAction()
    {
        switch (State)
        {
        case CharacterState.Idling:
            //reset morale
            Morale = COU.GetStatMax() * 2;

            if (actionInProgress)
            {
                if (navMeshAgent.remainingDistance < 0.02f)
                {
                    actionInProgress = false;
                }
            }
            else if (IrritationMeter >= IrritaionTolerance)
            {
                ChangeState(CharacterState.Attacking);
            }
            else if (Random.value < 0.015f)     //selecting idle action
            {
                (this as Goblin)?.Speak(PlayerController.GetDynamicReactions(PlayerController.DynamicState.Idle));

                actionInProgress = true;

                Vector3 dest;

                if (InArea)
                {
                    if (GetClosestEnemy() &&
                        (        //ANY friends fighting
                            InArea.PresentCharacters.Any(c => c.tag == tag && c.Alive() && c.Attacking())
                            // I am aggressive wanderer
                            || (StickToRoad && InArea.PresentCharacters.Any(c => c.tag == "Player" & !c.Hiding()))
                        ))
                    {
                        //Debug.Log(name + ": Joining attack without beeing attacked");

                        ChangeState(CharacterState.Attacking, true);
                        Morale -= 5;
                        Target  = GetClosestEnemy().transform.position;
                        dest    = Target;
                    }
                    else if ((this as Goblin) && Team && Team.Leader.InArea != InArea && Team.Leader.Idling())
                    {
                        dest = Team.Leader.InArea.GetRandomPosInArea();
                    }
                    else if ((this as Goblin) && tag == "Player" && GetClosestEnemy() && (GetClosestEnemy().transform.position - transform.position).magnitude < provokeDistance)
                    {
                        ChangeState(CharacterState.Provoking, true);
                        var ctx = GetClosestEnemy();
                        (this as Goblin).ProvokeTarget = ctx;
                        (this as Goblin)?.Speak(PlayerController.GetDynamicReactions(PlayerController.DynamicState.Mocking));
                        dest = ctx.transform.position;
                    }
                    else if (StickToRoad)
                    {
                        var goingTo = InArea.GetClosestNeighbour(transform.position, true);

                        dest = goingTo.PointOfInterest ? goingTo.GetRandomPosInArea(): goingTo.transform.position;

                        //Debug.Log(name + ": Wandering to "+ goingTo);
                        Target = dest;

                        goingTo.PresentCharacters.ForEach(c => StartCoroutine(c.SpotArrivalCheck(this)));

                        ChangeState(CharacterState.Travelling, true);
                    }
                    else
                    {
                        dest = InArea.GetRandomPosInArea();
                    }
                }
                else
                {
                    dest   = transform.position + Random.insideUnitSphere * idleDistance;
                    dest.y = 0;
                }

                navMeshAgent.SetDestination(dest);    //new Vector3(Random.Range(-idleDistance, idleDistance), 0,Random.Range(-idleDistance, idleDistance)));
            }
            //TODO: use a different method for activity selection than else if
            else if (Random.value < 0.0025f && this as Goblin && Team &&
                     !(Team.Leader == this) && (this as Goblin).ClassType > Goblin.Class.Slave
                     & !Team.Challenger && (Team.Leader as Goblin).CurrentLevel < ((Goblin)this).CurrentLevel)
            {
                //TODO: make it only appear after a while

                Debug.Log("Chief Fight!!");
                Team.ChallengeForLeadership(this as Goblin);
            }
            //TODO: define better which characters should search stuff
            else if (Random.value < 0.001f * SMA.GetStatMax() && Team && this as Goblin && !InArea.AnyEnemies() && InArea.Lootables.Any(l => !l.Searched))
            {
                var loots = InArea.Lootables.Where(l => !l.Searched).ToArray();

                var loot = loots[Random.Range(0, loots.Count())];

                (this as Goblin).Search(loot);
            }
            break;

        case CharacterState.Attacking:
            if (AttackTarget && AttackTarget.Alive() && AttackTarget.InArea == InArea)
            {
                if (AttackTarget.Fleeing())
                {
                    var c = GetClosestEnemy();
                    if (c)
                    {
                        AttackTarget = c;
                    }
                }

                navMeshAgent.SetDestination(AttackTarget.transform.position);

                //TODO: add random factor
            }
            else
            {
                TargetGone();
            }
            break;

        case CharacterState.Travelling:
            navMeshAgent.SetDestination(Target);
            //check for arrival and stop travelling
            if (Vector3.Distance(transform.position, Target) < 3f)
            {
                //Debug.Log(name +" arrived at target");
                State = CharacterState.Idling;

                actionInProgress = false;

                break;
            }

            break;

        case CharacterState.Fleeing:
            (this as Goblin)?.Speak(SoundBank.GoblinSound.PanicScream);

            //if (actionInProgress &! navMeshAgent.hasPath)
            //{
            //    //TODO: move into next if statement, if correct
            //    Debug.Log("stuck fleeing resolved");
            //    actionInProgress = false;
            //    ChangeState(CharacterState.Idling, true);
            //}
            if (fleeingToArea == InArea && navMeshAgent.remainingDistance < 0.1f)
            {
                actionInProgress = false;
                ChangeState(CharacterState.Idling, true);
            }
            else if (!actionInProgress)
            {
                fleeingToArea = InArea.GetClosestNeighbour(transform.position, StickToRoad);
                navMeshAgent.SetDestination(fleeingToArea.GetRandomPosInArea());

                actionInProgress = true;
            }
            break;

        case CharacterState.Dead:
            break;

        case CharacterState.Hiding:
            if (!Hidingplace)
            {
                State = CharacterState.Idling;
            }
            //already set the destination
            if ((navMeshAgent.destination - hiding.HideLocation.transform.position).sqrMagnitude < 1f)
            {
                if (InArea.AnyEnemies() && navMeshAgent.remainingDistance > 0.2f)
                {
                    ChangeState(CharacterState.Idling);
                }
            }
            else
            {
                navMeshAgent.SetDestination(hiding.HideLocation.transform.position);
            }
            break;

        //Only to be used for chief fights. TODO: rename
        case CharacterState.Watching:
            if (!Team || !Team.Challenger)
            {
                //cheer
                (this as Goblin)?.Speak(SoundBank.GoblinSound.Laugh);
                ChangeState(CharacterState.Idling, true);
            }
            else
            {
                if (Vector3.Distance(transform.position, Team.Challenger.transform.position) < 3f && Team.Challenger != this && Team.Leader != this)
                {
                    //cheer
                    (this as Goblin)?.Speak(PlayerController.GetDynamicReactions(PlayerController.DynamicState.ChiefBattleCheer));

                    navMeshAgent.ResetPath();
                }
                else if (!actionInProgress)
                {
                    navMeshAgent.SetDestination(Team.Challenger.transform.position);
                    actionInProgress = true;
                }
            }

            break;

        case CharacterState.Searching:
            //check for arrival and stop travelling
            if (Vector3.Distance(transform.position, LootTarget.transform.position) < 2f)
            {
                if (LootTarget.ContainsLoot)
                {
                    (this as Goblin)?.Speak(SoundBank.GoblinSound.Laugh);
                    PopUpText.ShowText(name + " found " + LootTarget.Loot);
                    Team.OnTreasureFound.Invoke(1);
                }
                if (LootTarget.ContainsFood)
                {
                    (this as Goblin)?.Speak(SoundBank.GoblinSound.Laugh);
                    PopUpText.ShowText(name + " found " + LootTarget.Food);
                    Team.OnFoodFound.Invoke(5);
                }
                if (this as Goblin)
                {
                    foreach (var equipment in LootTarget.EquipmentLoot)
                    {
                        //TODO: create player choice for selecting goblin
                        (this as Goblin)?.Speak(SoundBank.GoblinSound.Laugh);
                        PopUpText.ShowText(name + " found " + equipment.name);
                        if (Team && Team.Members.Count > 1)
                        {
                            Team.OnEquipmentFound.Invoke(equipment, this as Goblin);
                        }
                        else
                        {
                            Equip(equipment);
                        }
                    }
                }

                LootTarget.EquipmentLoot.Clear();

                LootTarget.ContainsFood = false;
                LootTarget.ContainsLoot = false;
                LootTarget.Searched     = true;

                State = CharacterState.Idling;
                break;
            }
            break;

        case CharacterState.Provoking:
            var g = this as Goblin;

            if (!g)
            {
                Debug.LogWarning("Non-goblin is being provocative");
                break;
            }

            if (!g.ProvokeTarget || g.ProvokeTarget.InArea != InArea)
            {
                (this as Goblin)?.Speak(SoundBank.GoblinSound.Laugh);
                g.ProvokeTarget = GetClosestEnemy();
            }

            if (!g.ProvokeTarget)
            {
                ChangeState(CharacterState.Idling, true);
                break;
            }

            if (g.ProvokeTarget.Attacking())
            {
                ChangeState(CharacterState.Attacking);
                break;
            }

            if (!actionInProgress && navMeshAgent.remainingDistance < 0.5f)
            {
                actionInProgress = true;
                navMeshAgent.SetDestination(g.ProvokeTarget.transform.position);
                ProvokeStartTime = Time.time;
                break;
            }

            if (ProvokeTime + ProvokeStartTime > Time.time)
            {
                //run away
                actionInProgress = false;
                var dest = InArea.GetRandomPosInArea();
                navMeshAgent.SetDestination(dest);
                g.ProvokeTarget.IrritationMeter++;
                break;
            }
            if ((g.ProvokeTarget.transform.position - transform.position).magnitude < 4)     //Provoke
            {
                navMeshAgent.isStopped = true;
                if (Random.value < 0.2f)
                {
                    (this as Goblin)?.Speak(
                        PlayerController.GetDynamicReactions(PlayerController.DynamicState.Mocking));
                }
            }
            break;

        case CharacterState.Surprised:
            navMeshAgent.isStopped = true;

            if (SurprisedTime + SurprisedStartTime <= Time.time)
            {
                ChangeState(CharacterState.Attacking);
            }
            break;

        case CharacterState.Resting:


            if (!Team || !Team.Campfire)
            {
                ChangeState(CharacterState.Idling, true);
            }
            else
            {
                if (Vector3.Distance(transform.position, Team.Campfire.transform.position) < 4f)
                {
                    (this as Goblin)?.Speak(SoundBank.GoblinSound.Eat);

                    navMeshAgent.ResetPath();
                }
                else if (!actionInProgress)
                {
                    navMeshAgent.SetDestination(Team.Campfire.transform.position);
                    actionInProgress = true;
                }
            }

            break;

        default:
            break;
        }
    }