예제 #1
0
        private IEnumerator CleanUpTurn(BattleMonster attackingMonster)
        {
            // Skip if battle is over.
            if (_state == BattleState.BattleOver)
            {
                yield break;
            }
            // Skip if monster is downed.
            if (_isMonsterDown)
            {
                _isMonsterDown = false;
                yield return(new WaitUntil(() => _state == BattleState.ExecutingTurn));

                yield break;
            }
            // Wait for monster switch, etc.
            yield return(new WaitUntil(() => _state == BattleState.ExecutingTurn));

            // Check for status changes like poison and update Monster/HUD.
            attackingMonster.Monster.CheckForStatusDamage();
            yield return(ShowStatusChanges(attackingMonster.Monster));

            yield return(attackingMonster.Hud.UpdateHp());

            if (attackingMonster.Monster.CurrentHp > 0)
            {
                yield break;
            }

            // Attacking monster was downed from status effects.
            yield return(HandleDownedMonster(attackingMonster));

            yield return(new WaitUntil(() => _state == BattleState.ExecutingTurn));
        }
예제 #2
0
    public void OnDungeonInfo()
    {
        MonsterCount  = DungeonUi.GetMonsterCount + 1;
        Difficulty_Lv = DungeonUi.GetDungeonLv;

        Debug.Log("Create DungeonLV " + Difficulty_Lv);
        Debug.Log("Create Monster Count " + MonsterCount);

        for (int i = 0; i < MonsterCount; i++)
        {
            m_PrefabMonster = Resources.Load("monster") as GameObject;
            GameObject    go = Instantiate(m_PrefabMonster) as GameObject;
            BattleMonster bm = go.GetComponent <BattleMonster>();

            m_monster.Add(bm);
        }

        foreach (var i in m_monster)
        {
            i.init();
        }

        m_DungeonStart = false;
        DungeonUi.transform.gameObject.SetActive(false);
    }
예제 #3
0
 private void CheckIfBattleIsOver(BattleMonster downedMonster)
 {
     if (downedMonster.IsPlayerMonster)
     {
         MonsterObj nextMonster = _playerParty.GetHealthyMonster();
         if (nextMonster != null)
         {
             OpenPartyScreen();
         }
         else
         {
             BattleOver(BattleResult.Lost);
         }
     }
     else
     {
         if (!_isCharBattle)
         {
             BattleOver(BattleResult.Won);
         }
         else
         {
             MonsterObj nextEnemyMonster = _battlerParty.GetHealthyMonster();
             if (nextEnemyMonster != null)
             {
                 StartCoroutine(ChoiceSelection(nextEnemyMonster));
             }
             else
             {
                 BattleOver(BattleResult.Won);
             }
         }
     }
 }
예제 #4
0
    public Monster(int pid, int num, RuntimeMonster RTData, MonsterData config)
    {
        this.pid    = pid;
        this.num    = num;
        this.RTData = RTData;

        InitConfig();

        this.inTeam = false;
        this.isNew  = true;
        //create the 战斗时候的运算数据对象
        this.BTData = new BattleMonster(baseAttack, enhanceAttack, baseDefend, enhanceDefend);
    }
예제 #5
0
 public void CancelSequence()
 {
     sequenceIndex    = -1;          // Hack to get the next to be 0
     target           = null;
     attackingPlayer  = null;
     attackValue      = 0;
     modAttackValue   = 0;
     attackSuccessful = false;
     diceCountChosen  = 0;
     if (CheckQuestComplete())
     {
         QuestVictory();
     }
     else
     {
         NextSequence();
     }
 }
예제 #6
0
        /// <summary>
        /// 设置当前场景
        /// </summary>
        public void SetState(SceneState sceneState, bool isNow = true, bool isAsync = false)
        {
            ISceneState State;

            switch (sceneState)
            {
            case SceneState.StartState:
                State = new StartState(this);
                break;

            case SceneState.MainScene:
                State = new MainScene(this);
                break;

            case SceneState.TrainScene:
                State = new TrainScene(this);
                break;

            case SceneState.VillageScene:
                State = new VillageScene(this);
                break;

            case SceneState.TutorialScene:
                State = new TutorialScene(this);
                break;

            case SceneState.BattleEyeball:
                State = new BattleEyeball(this);
                break;

            case SceneState.BattleMonster:
                State = new BattleMonster(this);
                break;

            case SceneState.BattleStrongKnight:
                State = new BattleStrongKnight(this);
                break;

            case SceneState.BattleFantasy:
                State = new BattleFantasy(this);
                break;

            case SceneState.BattleForestNight:
                State = new BattleForestNight(this);
                break;

            case SceneState.BattleForestDay:
                State = new BattleForestDay(this);
                break;

            default:
                return;
            }

            Debug.Log("切换场景:" + State.ToString());
            isSceneBegin = false;

            // 通知前一個State結束
            if (CurState != null)
            {
                CurState.StateEnd();
            }
            // 载入场景
            if (isNow)
            {
                if (isAsync)
                {
                    UILoading.nextScene = State.StateName;
                    LoadScene("Loading");
                }
                else
                {
                    LoadScene(State.StateName);
                }
            }
            //设置当前场景
            CurState = State;
        }
예제 #7
0
        /// <summary>
        /// Play the Capture Crystal animation.
        /// </summary>
        /// <param name="playerMonster">Player's monster</param>
        /// <param name="enemyMonster">Enemy's monster</param>
        /// <param name="beamCount">Count returned by capture algo determines the animation length.</param>
        /// <returns></returns>
        public IEnumerator PlayCrystalAnimation(BattleMonster playerMonster, BattleMonster enemyMonster, int beamCount)
        {
            // Factory or Flyweight pattern for this?

            /*
             * TODO - refactor this animation, i'm sure there's a better way to do this
             * My thinking was I wanted absolute control over where to position things and it seemed easiest
             * to just create this massive block of code to achieve it, but I'm sure my inexperience is showing here big time.
             * If it seems stupid, but it works, then I guess its not so stupid.
             */
            //TODO - instantiate these under _Dynamic
            // Build the animation points.
            Vector3 enemyPosition = enemyMonster.transform.position;
            Vector3 origin        = playerMonster.transform.position - new Vector3(2, 0);
            Vector3 destination   = enemyPosition - new Vector3(5, 2);

            // Deploy the capture crystal.
            _crystalObj = Instantiate(_crystalSprite, origin, Quaternion.identity);
            var crystal = _crystalObj.GetComponent <SpriteRenderer>();

            crystal.transform.localScale = new Vector3(0.2f, 0.2f);
            crystal.transform.DOScale(1, 1f);
            yield return(crystal.transform.DOJump(destination, 2f, 1, 1f).WaitForCompletion());

            enemyMonster.PlayCaptureAnimation();

            // Send the first beam and instantiate the burst.
            _beamObj1 = Instantiate(_beamSprite, destination + new Vector3(0, 2), Quaternion.Euler(0, 0, 270));
            var beam1 = _beamObj1.GetComponent <SpriteRenderer>();

            yield return(beam1.transform.DOLocalMove(enemyPosition, 0.5f));

            beam1.DOFade(0, 0.5f);

            _burstObj = Instantiate(_burstSprite, enemyPosition, Quaternion.identity);
            var burst = _burstObj.GetComponent <SpriteRenderer>();

            yield return(YieldHelper.TwoSeconds);

            // Quit after 1 beam.
            if (beamCount == 0 || beamCount == 1)
            {
                yield break;
            }

            // Send the second beam and grow the burst.
            _beamObj2 = Instantiate(_beamSprite, destination + new Vector3(0, -2), Quaternion.Euler(0, 0, 310));
            var beam2 = _beamObj2.GetComponent <SpriteRenderer>();

            yield return(beam2.transform.DOLocalMove(enemyPosition, 0.5f));

            beam2.DOFade(0, 0.5f);

            burst.transform.DOScale(5f, 0.5f);
            yield return(YieldHelper.TwoSeconds);

            // Quit after 2 beams.
            if (beamCount == 2)
            {
                yield break;
            }

            // Send the final beam and grow the burst to max size.
            _beamObj3 = Instantiate(_beamSprite, destination, Quaternion.Euler(0, 0, 290));
            var beam3 = _beamObj3.GetComponent <SpriteRenderer>();

            yield return(beam3.transform.DOLocalMove(enemyPosition, 0.5f));

            burst.transform.DOScale(10f, 0.5f);
            beam3.DOFade(0, 0.5f);
            yield return(YieldHelper.TwoSeconds);

            // Quit after 3 beams.
            if (beamCount == 3)
            {
                yield break;
            }

            // Play the capture animation.
            enemyMonster.Image.DOFade(0, 0.1f);
            burst.transform.DOLocalMove(destination, 1f);
            yield return(burst.DOFade(0, 1f));

            crystal.transform.DOScale(2f, 1.5f);
            yield return(YieldHelper.OneSecond);

            crystal.transform.DOLocalMove(origin, 1.5f);
            crystal.DOFade(0f, 1.5f);
            yield return(YieldHelper.TwoSeconds);
        }
예제 #8
0
        private IEnumerator HandleDownedMonster(BattleMonster downedMonster)
        {
            _isMonsterDown = true;
            if (downedMonster.IsPlayerMonster)
            {
                yield return(_dialogBox.TypeDialog($"{downedMonster.Monster.Base.Name} has been taken down!"));
            }
            else
            {
                yield return(_dialogBox.TypeDialog($"Enemy {downedMonster.Monster.Base.Name} has been taken down!"));
            }

            downedMonster.PlayDownedAnimation();
            yield return(YieldHelper.TwoSeconds);

            if (!downedMonster.IsPlayerMonster)
            {
                // Setup exp gain variables.
                int   expBase      = downedMonster.Monster.Base.ExpGiven;
                int   enemyLevel   = downedMonster.Monster.Level;
                float battlerBonus = _isCharBattle ? 1.5f : 1f;

                // Handle exp gain.
                int expGain = Mathf.FloorToInt(expBase * enemyLevel * battlerBonus / 7);
                _playerMonster.Monster.Exp += expGain;
                yield return(_dialogBox.TypeDialog($"{_playerMonster.Monster.Base.Name} has gained {expGain.ToString()} experience!"));

                yield return(_playerMonster.Hud.SlideExp());

                // While loop in case the monster gains more than 1 level.
                while (_playerMonster.Monster.CheckForLevelUp())
                {
                    _playerMonster.Hud.SetLevel();
                    yield return(_dialogBox.TypeDialog($"{_playerMonster.Monster.Base.Name} has leveled up, they are now level {_playerMonster.Monster.Level.ToString()}!"));

                    yield return(_playerMonster.Hud.SlideExp(true));

                    // Learn a new move.
                    LearnableMove newMove = _playerMonster.Monster.GetLearnableMove();
                    if (newMove == null)
                    {
                        continue;
                    }

                    if (_playerMonster.Monster.Moves.Count < MonsterBase.MaxNumberOfMoves)
                    {
                        _playerMonster.Monster.LearnMove(newMove);
                        _dialogBox.SetMoveList(_playerMonster.Monster.Moves);
                        yield return(_dialogBox.TypeDialog($"{_playerMonster.Monster.Base.Name} has learned {newMove.Base.Name}!"));
                    }
                    else
                    {
                        // Forget an existing move first.
                        yield return(ForgetMoveSelection(_playerMonster.Monster, newMove));
                    }
                }

                yield return(YieldHelper.OneSecond);
            }

            // Wait until move learning is finished before calling CheckIfBattleIsOver.
            yield return(new WaitUntil(() => _state == BattleState.ExecutingTurn));

            CheckIfBattleIsOver(downedMonster);
        }
예제 #9
0
        private IEnumerator UseMove(BattleMonster attackingMonster, BattleMonster defendingMonster, MoveObj move)
        {
            // Check for statuses like paralyze or sleep before trying to attack.
            bool canAttack = attackingMonster.Monster.CheckIfCanAttack();

            if (!canAttack)
            {
                yield return(ShowStatusChanges(attackingMonster.Monster));

                yield return(attackingMonster.Hud.UpdateHp());

                yield break;
            }

            // Clear the StatusChanges queue and decrease the move energy.
            yield return(ShowStatusChanges(attackingMonster.Monster));

            move.Energy--;
            if (attackingMonster.IsPlayerMonster)
            {
                yield return(_dialogBox.TypeDialog($"{attackingMonster.Monster.Base.Name} used {move.Base.Name}!"));
            }
            else
            {
                yield return(_dialogBox.TypeDialog($"Enemy {attackingMonster.Monster.Base.Name} used {move.Base.Name}!"));
            }

            if (CheckIfMoveHits(move, attackingMonster.Monster, defendingMonster.Monster))
            {
                attackingMonster.PlayAttackAnimation();
                yield return(YieldHelper.HalfSecond);

                defendingMonster.PlayHitAnimation();

                // If status move then don't deal damage, switch to UseMoveEffects coroutine.
                if (move.Base.Category == MoveCategory.Status)
                {
                    yield return(UseMoveEffects(move.Base.Effects, attackingMonster.Monster, defendingMonster.Monster,
                                                move.Base.Target));
                }
                else
                {
                    DamageDetails damageDetails = defendingMonster.Monster.TakeDamage(move, attackingMonster.Monster);
                    yield return(defendingMonster.Hud.UpdateHp());

                    yield return(ShowDamageDetails(damageDetails));
                }

                // Check for secondary move effects.
                if (move.Base.MoveSecondaryEffects != null &&
                    move.Base.MoveSecondaryEffects.Count > 0 &&
                    attackingMonster.Monster.CurrentHp > 0)
                {
                    foreach (MoveSecondaryEffects effect in move.Base.MoveSecondaryEffects)
                    {
                        int rng = UnityEngine.Random.Range(1, 101);
                        if (rng <= effect.Chance)
                        {
                            yield return(UseMoveEffects(effect, attackingMonster.Monster, defendingMonster.Monster,
                                                        effect.Target));
                        }
                    }
                }

                // Handle downed monster and check if we should continue.
                if (defendingMonster.Monster.CurrentHp <= 0)
                {
                    yield return(HandleDownedMonster(defendingMonster));
                }
            }
            else
            {
                // Handle a missed attack.
                if (attackingMonster.IsPlayerMonster)
                {
                    yield return(_dialogBox.TypeDialog($"{attackingMonster.Monster.Base.Name} missed their attack!"));
                }
                else
                {
                    yield return(_dialogBox.TypeDialog($"Enemy {attackingMonster.Monster.Base.Name} missed their attack!"));
                }
            }
        }
예제 #10
0
        private IEnumerator ExecuteTurn(BattleAction playerAction)
        {
            _state = BattleState.ExecutingTurn;
            if (playerAction == BattleAction.Move)
            {
                // Get the monster moves.
                _playerMonster.Monster.CurrentMove = _playerMonster.Monster.Moves[_currentMove];
                _enemyMonster.Monster.CurrentMove  = _enemyMonster.Monster.GetRandomMove();
                if (_playerMonster.Monster.CurrentMove == null || _enemyMonster.Monster.CurrentMove == null)
                {
                    BattleOver(BattleResult.Error);
                    yield break;
                }

                int playerPriority = _playerMonster.Monster.CurrentMove.Base.Priority;
                int enemyPriority  = _enemyMonster.Monster.CurrentMove.Base.Priority;

                // Check who goes first.
                var isPlayerFirst = true;
                if (enemyPriority > playerPriority)
                {
                    isPlayerFirst = false;
                }
                else if (playerPriority == enemyPriority)
                {
                    isPlayerFirst = _playerMonster.Monster.Speed >= _enemyMonster.Monster.Speed;
                }

                BattleMonster firstMonster  = (isPlayerFirst) ? _playerMonster : _enemyMonster;
                BattleMonster secondMonster = (isPlayerFirst) ? _enemyMonster : _playerMonster;

                // Store in case it gets downed and switched out before its move.
                MonsterObj lastMonster = secondMonster.Monster;

                // Execute the first move.
                yield return(UseMove(firstMonster, secondMonster, firstMonster.Monster.CurrentMove));

                yield return(CleanUpTurn(firstMonster));

                if (_state == BattleState.BattleOver)
                {
                    yield break;
                }

                // Execute the second move.
                if (lastMonster.CurrentHp > 0)
                {
                    yield return(UseMove(secondMonster, firstMonster, secondMonster.Monster.CurrentMove));

                    yield return(CleanUpTurn(secondMonster));

                    if (_state == BattleState.BattleOver)
                    {
                        yield break;
                    }
                }
            }
            else if (playerAction == BattleAction.SwitchMonster)
            {
                // Switch the monster.
                MonsterObj selectedMember = _playerParty.Monsters[_currentMember];
                _state = BattleState.Busy;
                yield return(SwitchMonster(selectedMember));

                // Now it's the enemy's turn.
                MoveObj enemyMove = _enemyMonster.Monster.GetRandomMove();
                if (enemyMove == null)
                {
                    BattleOver(BattleResult.Error);
                    yield break;
                }

                yield return(UseMove(_enemyMonster, _playerMonster, enemyMove));

                yield return(CleanUpTurn(_enemyMonster));

                if (_state == BattleState.BattleOver)
                {
                    yield break;
                }
            }
            else if (playerAction == BattleAction.UseItem)
            {
                //TODO - refactor this when item system is implemented.
                // Use the item.
                _dialogBox.EnableActionSelector(false);
                yield return(ActivateCrystal());
            }
            else if (playerAction == BattleAction.Run)
            {
                // Run from the battle.
                yield return(AttemptRun());
            }

            // Return to ActionSelection.
            if (_state != BattleState.BattleOver)
            {
                ActionSelection();
            }
        }