示例#1
0
        private int AttemptCapture(MonsterObj monster)
        {
            // Algo is from g3/4.
            float a = (3 * monster.MaxHp - 2 * monster.CurrentHp) * monster.Base.CatchRate *
                      ConditionDB.GetStatusBonus(monster.Status) / (3 * monster.MaxHp);

            if (a >= 255)
            {
                return(4);
            }

            float b = 1048560 / Mathf.Sqrt(Mathf.Sqrt(16711680 / a));

            var beamCount = 0;

            while (beamCount < 4)
            {
                if (UnityEngine.Random.Range(0, 65535) >= b)
                {
                    break;
                }

                ++beamCount;
            }

            return(beamCount);
        }
示例#2
0
        private IEnumerator SwitchMonster(MonsterObj newMonster)
        {
            if (_playerMonster.Monster.CurrentHp > 0)
            {
                yield return(_dialogBox.TypeDialog($"{_playerMonster.Monster.Base.Name}, fall back!"));

                _playerMonster.PlayDownedAnimation(); //TODO - create animation for returning to party
                yield return(YieldHelper.TwoSeconds);
            }

            _playerMonster.Setup(newMonster);
            _dialogBox.SetMoveList(newMonster.Moves);
            yield return(_dialogBox.TypeDialog($"It's your turn now, {newMonster.Base.Name}!"));

            // Allow player to switch monsters after enemy replaces a downed monster.
            if (_prevState == null)
            {
                _state = BattleState.ExecutingTurn;
            }
            else if (_prevState == BattleState.ChoiceSelection)
            {
                _prevState = null;
                StartCoroutine(SwitchEnemyMonster());
            }
        }
示例#3
0
        private IEnumerator UseMoveEffects(MoveEffects effects, MonsterObj attackingMonster, MonsterObj defendingMonster,
                                           MoveTarget moveTarget)
        {
            // Handle any stat changes.
            if (effects.StatChanges != null)
            {
                if (moveTarget == MoveTarget.Self)
                {
                    attackingMonster.ApplyStatChanges(effects.StatChanges);
                }
                else
                {
                    defendingMonster.ApplyStatChanges(effects.StatChanges);
                }
            }

            // Handle any status conditions.
            if (effects.Status != ConditionID.None)
            {
                defendingMonster.SetStatus(effects.Status);
            }

            // Handle any volatile status conditions.
            if (effects.VolatileStatus != ConditionID.None)
            {
                defendingMonster.SetVolatileStatus(effects.VolatileStatus);
            }

            yield return(ShowStatusChanges(attackingMonster));

            yield return(ShowStatusChanges(defendingMonster));
        }
示例#4
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);
             }
         }
     }
 }
示例#5
0
 private IEnumerator ShowStatusChanges(MonsterObj monster)
 {
     while (monster.StatusChanges.Count > 0)
     {
         string message = monster.StatusChanges.Dequeue();
         yield return(_dialogBox.TypeDialog(message));
     }
 }
示例#6
0
        private IEnumerator ChoiceSelection(MonsterObj nextMonster)
        {
            _state = BattleState.Busy;
            yield return(_dialogBox.TypeDialog($"{_battler.Name} is about to deploy {nextMonster.Base.Name}! Do you want to switch your Battokuri too?"));

            _state = BattleState.ChoiceSelection;
            _dialogBox.EnableChoiceSelector(true);
        }
示例#7
0
        /// <summary>
        /// Get a random monster from the available pool.
        /// </summary>
        /// <returns>Monster to encounter.</returns>
        public MonsterObj GetRandomMonster()
        {
            //TODO - refactor this for monster rarity
            MonsterObj wildMonster = _wildMonsters[Random.Range(0, _wildMonsters.Count)];

            wildMonster.Init();
            return(wildMonster);
        }
示例#8
0
 /// <summary>
 /// Starts a battle with a wild monster.
 /// </summary>
 /// <param name="playerParty">Player's party of monsters.</param>
 /// <param name="wildMonster">Copy of the wild monster generated from the MapLayer.</param>
 public void StartWildBattle(MonsterParty playerParty, MonsterObj wildMonster)
 {
     _playerParty  = playerParty;
     _wildMonster  = wildMonster;
     _isCharBattle = false;
     _player       = playerParty.GetComponent <PlayerController>();
     StartCoroutine(SetupBattle());
 }
示例#9
0
        private IEnumerator ForgetMoveSelection(MonsterObj monster, LearnableMove newMove)
        {
            _prevState = BattleState.ForgetSelection;
            _state     = BattleState.Busy;
            yield return(_dialogBox.TypeDialog($"{monster.Base.Name} can learn {newMove.Base.Name}, but it's move list is full. Forget a move to learn {newMove.Base.Name}?"));

            _state = BattleState.ChoiceSelection;
            _dialogBox.EnableChoiceSelector(true);
        }
示例#10
0
        private IEnumerator SwitchEnemyMonster()
        {
            _state = BattleState.Busy;
            MonsterObj nextMonster = _battlerParty.GetHealthyMonster();

            _enemyMonster.Setup(nextMonster);

            yield return(_dialogBox.TypeDialog($"{_battler.Name} has deployed {nextMonster.Base.Name} to the battle!"));

            _state = BattleState.ExecutingTurn;
        }
示例#11
0
        /// <summary>
        /// Starts a battle with a wild monster after Encounter collider is triggered.
        /// </summary>
        public void StartWildBattle()
        {
            _state = GameState.Battle;
            _battleSystem.gameObject.SetActive(true);
            _worldCamera.gameObject.SetActive(false);

            var        playerParty  = _playerController.GetComponent <MonsterParty>();
            MonsterObj wildMonster  = FindObjectOfType <MapArea>().GetComponent <MapArea>().GetRandomMonster();
            var        enemyMonster = new MonsterObj(wildMonster.Base, wildMonster.Level);

            _battleSystem.StartWildBattle(playerParty, enemyMonster);
        }
示例#12
0
        private IEnumerator ForgetMove(MonsterObj monster, MoveObj oldMove)
        {
            //TODO - fix bug where new move is lost if monster gains more than one level
            LearnableMove newMove = _playerMonster.Monster.GetLearnableMove();

            monster.ForgetMove(oldMove);
            monster.LearnMove(newMove);
            _dialogBox.SetMoveList(monster.Moves);

            yield return(_dialogBox.TypeDialog($"{_playerMonster.Monster.Base.Name} has forgotten {oldMove.Base.Name}!"));

            yield return(_dialogBox.TypeDialog($"{_playerMonster.Monster.Base.Name} has learned {newMove.Base.Name}!"));

            _state = BattleState.ExecutingTurn;
        }
示例#13
0
        /// <summary>
        /// Creates a new save game data.
        /// </summary>
        /// <param name="playerName">New player's name.</param>
        /// <param name="monsterChoice">New player's choice of starting monster.</param>
        public static void NewGameData(string playerName, string monsterChoice)
        {
            // Create a new player and place it in the starting spot.
            _playerData = new PlayerData(playerName, "World.Fornwest.Main", new[] { 1, 1 });

            // Create the starter monster and add it to the party.
            var monsterBase    = Resources.Load <MonsterBase>($"Monsters/{monsterChoice}");
            var starterMonster = new MonsterObj(monsterBase, 5);

            _partyMonsters.Clear();
            _partyMonsters.Add(starterMonster.SaveMonsterData());

            // Data is ready so now we signal the new game.
            GameSignals.GAME_NEW.Dispatch(_playerData.id);
            Debug.Log($"New game: {_playerData.id} created.");
        }
示例#14
0
 /// <summary>
 /// Set the data in the HUD.
 /// </summary>
 /// <param name="monster">Monster to set data for.</param>
 public void SetData(MonsterObj monster)
 {
     _monster       = monster;
     _nameText.text = monster.Base.Name;
     SetLevel();
     SetExp();
     _hpBar.SetHp((float)monster.CurrentHp / monster.MaxHp);
     _statusColors = new Dictionary <ConditionID, Color>
     {
         { ConditionID.Poison, _psnColor },
         { ConditionID.Burn, _brnColor },
         { ConditionID.Sleep, _slpColor },
         { ConditionID.Paralyze, _parColor },
         { ConditionID.Freeze, _frzColor }
     };
     SetStatusText();
     _monster.OnStatusChange += SetStatusText;
 }
示例#15
0
        private IEnumerator SetupBattle()
        {
            //TODO - handle case with no healthy monsters
            _playerMonster.HideHud();
            _enemyMonster.HideHud();
            if (!_isCharBattle)
            {
                _playerMonster.Setup(_playerParty.GetHealthyMonster());
                _enemyMonster.Setup(_wildMonster);
                _dialogBox.SetMoveList(_playerMonster.Monster.Moves);
                yield return(_dialogBox.TypeDialog($"You have encountered an enemy {_enemyMonster.Monster.Base.Name}!"));
            }
            else
            {
                ShowCharacterSprites();
                yield return(_dialogBox.TypeDialog($"{_battler.Name} has challenged you to a battle!"));

                // Deploy enemy monster.
                _battlerImage.gameObject.SetActive(false); //TODO - animate this
                _enemyMonster.gameObject.SetActive(true);
                MonsterObj enemyLeadMonster = _battlerParty.GetHealthyMonster();
                _enemyMonster.Setup(enemyLeadMonster);
                yield return(_dialogBox.TypeDialog($"{_battler.Name} has deployed {enemyLeadMonster.Base.Name} to the battle!"));

                // Deploy player monster.
                _playerImage.gameObject.SetActive(false); //TODO - animate this too
                _playerMonster.gameObject.SetActive(true);
                MonsterObj playerLeadMonster = _playerParty.GetHealthyMonster();
                _playerMonster.Setup(playerLeadMonster);
                _dialogBox.SetMoveList(_playerMonster.Monster.Moves);
                yield return(_dialogBox.TypeDialog($"You have deployed {playerLeadMonster.Base.Name} to the battle!"));
            }

            _escapeAttempts = 0;
            _partyScreen.Init();
            ActionSelection();
        }
示例#16
0
        private bool CheckIfMoveHits(MoveObj move, MonsterObj attackingMonster, MonsterObj defendingMonster)
        {
            if (move.Base.AlwaysHits)
            {
                return(true);
            }

            // Stat changes based on original game's formula.
            float moveAccuracy = move.Base.Accuracy;
            int   accuracy     = attackingMonster.StatsChanged[MonsterStat.Accuracy];
            int   evasion      = defendingMonster.StatsChanged[MonsterStat.Evasion];

            float[] changeVals = { 1f, 4f / 3f, 5f / 3f, 2f, 7f / 3f, 8f / 3f, 3f };

            if (accuracy > 0)
            {
                moveAccuracy *= changeVals[accuracy];
            }
            else if (accuracy < 0)
            {
                moveAccuracy /= changeVals[-accuracy];
            }

            if (evasion > 0)
            {
                moveAccuracy /= changeVals[evasion];
            }
            else if (evasion < 0)
            {
                moveAccuracy *= changeVals[evasion];
            }

            int rng = UnityEngine.Random.Range(1, 101);

            return(rng <= moveAccuracy);
        }
示例#17
0
 /// <summary>
 /// Populate the UI with Monster data.
 /// </summary>
 /// <param name="monster">Monster in party.</param>
 public void SetData(MonsterObj monster)
 {
     _nameText.text  = monster.Base.Name;
     _levelText.text = "Lvl " + monster.Level;
     _hpBar.SetHp((float)monster.CurrentHp / monster.MaxHp);
 }
示例#18
0
        private void HandlePartySelection()
        {
            if (Keyboard.current.rightArrowKey.wasPressedThisFrame)
            {
                ++_currentMember;
            }
            else if (Keyboard.current.leftArrowKey.wasPressedThisFrame)
            {
                --_currentMember;
            }
            else if (Keyboard.current.downArrowKey.wasPressedThisFrame)
            {
                _currentMember += 3;
            }
            else if (Keyboard.current.upArrowKey.wasPressedThisFrame)
            {
                _currentMember -= 3;
            }

            _currentMember = Mathf.Clamp(_currentMember, 0, _playerParty.Monsters.Count - 1);
            _partyScreen.UpdateMemberSelection(_currentMember);

            if (Keyboard.current.zKey.wasPressedThisFrame)
            {
                MonsterObj selectedMember = _playerParty.Monsters[_currentMember];
                if (selectedMember.CurrentHp <= 0)
                {
                    _partyScreen.SetMessageText("That Battokuri is downed and cannot be used!");
                    return;
                }

                if (selectedMember == _playerMonster.Monster)
                {
                    _partyScreen.SetMessageText("That Battokuri is already being used!");
                    return;
                }

                _partyScreen.gameObject.SetActive(false);
                // If player switched monster voluntarily it should count as a turn move
                // If monster was downed and forced switch then it should trigger a new turn
                if (_prevState == BattleState.ActionSelection)
                {
                    _prevState = null;
                    StartCoroutine(ExecuteTurn(BattleAction.SwitchMonster));
                }
                else
                {
                    _state = BattleState.Busy;
                    StartCoroutine(SwitchMonster(selectedMember));
                }
            }
            else if (Keyboard.current.xKey.wasPressedThisFrame)
            {
                if (_playerMonster.Monster.CurrentHp <= 0)
                {
                    _partyScreen.SetMessageText("You must select a Battokuri!");
                    return;
                }

                _partyScreen.gameObject.SetActive(false);
                if (_prevState == BattleState.ChoiceSelection)
                {
                    _prevState = null;
                    StartCoroutine(SwitchEnemyMonster());
                }
                else
                {
                    ActionSelection();
                }
            }
        }
示例#19
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();
            }
        }
示例#20
0
        /// <summary>
        /// 查找目标。
        /// </summary>
        private void FindTarget()
        {
            PlayerObj player = CoreEntry.gActorMgr.MainPlayer;

            if (player == null)
            {
                return;
            }

            //有任务在身时,判断任务位置
            Vector3 selfpos = player.transform.position;
            int     mid     = 0;

            LogMgr.LogAI("AutoAIFindTarget.FindTarget");
            if (TaskMgr.RunTaskType != 0 && !IsInDungeon())
            {
                mid = TaskMgr.Instance.GetCurTargetMonsterId();
                if (mid != 0)
                {
                    const float RESET_DISTANCE = 5;             //重新回到任务点距离
                    Vector3     pos            = TaskMgr.Instance.goPos;
                    float       x = selfpos.x - pos.x;
                    float       z = selfpos.z - pos.z;
                    if (x * x + z * z >= RESET_DISTANCE * RESET_DISTANCE)
                    {
                        LogMgr.LogAI("AutoAIFindTarget.FindTarget 离开任务目标位置太远,重新回去");
                        m_TargetPosition = pos;
                        m_IsHaveTarget   = true;
                        return;
                    }
                }
            }

            int      mapid = MapMgr.Instance.EnterMapId;
            LuaTable cfg   = ConfigManager.Instance.Map.GetMapConfig(mapid);
            ActorObj actor = player.FindTarget(cfg.Get <int>("autoFightRange"), mapid);

            if (actor != null)
            {
                //如果选择的不是当前怪物则忽略
                if (mid != 0 && actor is MonsterObj)
                {
                    MonsterObj monster = actor as MonsterObj;
                    if (monster.ConfigID != mid)
                    {
                        return;
                    }
                }

                m_TargetPosition = actor.transform.position;
                m_IsHaveTarget   = true;
                return;
            }

            if (MapMgr.Instance.CurMapType == MapMgr.MapType.Map_CrossServer)
            {
                return;
            }


            //向服务器查询位置
            if (WildQuery || IsInDungeon())
            {
                //加载查询列表
                if (m_QueryList.Count <= 0)
                {
                    m_QueryList  = GetSortedEntList(player.transform.position);
                    m_QueryIndex = 0;
                }

                //开始查询
                if (m_QueryList.Count > 0)
                {
                    Vector3 pos = m_QueryList[m_QueryIndex];
                    m_QueryIndex       = (m_QueryIndex + 1) % m_QueryList.Count;
                    m_IsRequestPositon = true;
                    m_QueryWaitCount   = 5;
                    NetLogicGame.Instance.SendQueryMonsterByPosition((int)(pos.x * 1000), (int)(pos.z * 1000));
                    LogMgr.LogAI("AutoAIFindTarget.FindTarget RequestPositon:{0}", pos);
                }
                else
                {
                    LogMgr.LogAI("AutoAIFindTarget.FindTarget The QueryList is empty!");
                }
            }
            else
            {
                LogMgr.LogAI("AutoAIFindTarget.FindTarget Can not find target.");
            }
        }