IEnumerator NextTurnWithDelay(int oldTurn)
    {
        bool ready;

        /* 페이즈 1: 일반 피격 애니메이션 재생 */
        if (oldTurn == 0)
        {
            // 플레이어의 턴이 끝남
            foreach (Character e in enemies)
            {
                e.DamagedAnimation();
            }
        }
        else if (oldTurn == 1)
        {
            // 적들의 턴이 끝남
            player.DamagedAnimation();
        }

        while (true)
        {
            ready = true;
            foreach (Character e in enemies)
            {
                if (e.Alive && e.Mover.IsMoving)
                {
                    ready = false;
                    break;
                }
            }
            if (player.Alive && player.Mover.IsMoving)
            {
                ready = false;
            }

            if (ready)
            {
                break;
            }
            else
            {
                yield return(null);
            }
        }

        /* 페이즈 2: 무기 특수 효과(흡수) 대미지 애니메이션 처리 */
        if (oldTurn == 0)
        {
            // 흡수 효과의 회복 처리
            if (player.EquippedWeapon.drainedPercent > 0f && player.attackSum > 0)
            {
                player.Drained();
            }
            player.attackSum = 0;
        }
        else if (oldTurn == 1)
        {
            // 적들의 턴이 끝남
            foreach (Character e in enemies)
            {
                // 흡수 효과의 회복 처리
                if (e.EquippedWeapon.drainedPercent > 0f && e.attackSum > 0)
                {
                    e.Drained();
                }
                e.attackSum = 0;
            }
        }

        while (true)
        {
            ready = true;
            foreach (Character e in enemies)
            {
                if (e.Alive && e.Mover.IsMoving)
                {
                    ready = false;
                    break;
                }
            }
            if (player.Alive && player.Mover.IsMoving)
            {
                ready = false;
            }

            if (ready)
            {
                break;
            }
            else
            {
                yield return(null);
            }
        }

        /* 페이즈 3: 무기 특수 효과(중독, 돌풍) 대미지 애니메이션 처리 */
        if (oldTurn == 0)
        {
            // 플레이어의 턴이 끝남
            foreach (Character e in enemies)
            {
                // 돌풍 효과의 대미지 처리
                if (e.gustDamage > 0)
                {
                    e.Gusted();
                }
            }

            // 중독 효과의 대미지 처리
            if (player.poisonDamage > 0)
            {
                player.Poisoned();
            }
        }
        else if (oldTurn == 1)
        {
            // 적들의 턴이 끝남
            foreach (Character e in enemies)
            {
                // 중독 효과의 대미지 처리
                if (e.poisonDamage > 0)
                {
                    e.Poisoned();
                }
            }
        }

        while (true)
        {
            ready = true;
            foreach (Character e in enemies)
            {
                if (e.Alive && e.Mover.IsMoving)
                {
                    ready = false;
                    break;
                }
            }
            if (player.Alive && player.Mover.IsMoving)
            {
                ready = false;
            }

            if (ready)
            {
                break;
            }
            else
            {
                yield return(null);
            }
        }

        /* 페이즈 4: 방어구 특수 효과(반사, 재생) 대미지 애니메이션 처리 */
        if (oldTurn == 0)
        {
            foreach (Character e in enemies)
            {
                e.armor.InvokeArmorEffects(e);

                // 턴을 넘길 때의 각 적의 현재 체력을 기억
                e.oldHealth = e.currentHealth;
            }
            player.Reflected();
            foreach (Character e in enemies)
            {
                e.Regenerated();
            }
            // 턴을 넘길 때의 플레이어의 현재 체력을 기억
            player.oldHealth     = player.currentHealth;
            player.trueOldHealth = player.currentHealth;
        }
        else if (oldTurn == 1)
        {
            player.armor.InvokeArmorEffects(player);
            foreach (Character e in enemies)
            {
                e.Reflected();
                // 턴을 넘길 때의 각 적의 현재 체력을 기억
                e.oldHealth     = e.currentHealth;
                e.trueOldHealth = e.currentHealth;
            }
            player.Regenerated();
            player.oldHealth = player.currentHealth;
        }

        while (true)
        {
            ready = true;
            foreach (Character e in enemies)
            {
                if (e.Alive && e.Mover.IsMoving)
                {
                    ready = false;
                    break;
                }
            }
            if (player.Alive && player.Mover.IsMoving)
            {
                ready = false;
            }

            if (ready)
            {
                break;
            }
            else
            {
                yield return(null);
            }
        }

        /* 페이즈 5: 제한 턴 초과에 의한 대미지 애니메이션 처리 */
        if (oldTurn == 0)
        {
            if (RemainedTurn == 0)
            {
                player.Damaged(player.MaxHealth, new Vector3(0f, 0f, 0f), true);
                player.DamagedAnimation();

                // 턴을 넘길 때의 플레이어의 현재 체력을 기억
                player.oldHealth     = player.currentHealth;
                player.trueOldHealth = player.currentHealth;
            }
        }
        else if (oldTurn == 1)
        {
        }

        while (true)
        {
            ready = true;
            if (player.Alive && player.Mover.IsMoving)
            {
                ready = false;
            }

            if (ready)
            {
                break;
            }
            else
            {
                yield return(null);
            }
        }

        // 사망 여부 확인
        player.DeathCheck();
        foreach (Character e in enemies)
        {
            e.DeathCheck();
        }

        /* 페이즈 6: 탈바꿈 애니메이션 처리 */
        if (oldTurn == 0)
        {
        }
        else if (oldTurn == 1)
        {
            foreach (Character e in enemies)
            {
                e.armor.InvokeActiveArmorEffects(e);
                // 턴을 넘길 때의 각 적의 현재 체력을 기억
                e.oldHealth     = e.currentHealth;
                e.trueOldHealth = e.currentHealth;
            }
            player.oldHealth = player.currentHealth;
        }

        while (true)
        {
            ready = true;
            foreach (Character e in enemies)
            {
                if (e.Alive && e.Mover.IsMoving)
                {
                    ready = false;
                    break;
                }
            }
            if (player.Alive && player.Mover.IsMoving)
            {
                ready = false;
            }

            if (ready)
            {
                break;
            }
            else
            {
                yield return(null);
            }
        }

        monsterNumberText.text = MonsterNumber.ToString();
        if (MonsterNumber == 0)
        {
            monsterNumberText.color = ColorManager.cm.monsterNumberColors[0];
            if (!monsterEliminated)
            {
                monsterEliminated = true;
                Canvas.GetComponent <UIInfo>().notiPanel.GetComponent <NotiUI>().SetNotiText("All monsters were eliminated.");
            }
        }
        else
        {
            monsterNumberText.color = ColorManager.cm.monsterNumberColors[1];
        }

        turn = (oldTurn + 1) % 2;

        if (turn == 1)
        {
            TurnNumber++;
        }
    }
Example #2
0
 public void StartThreadingScan()
 {
     MonsterInfoScanRef = new ThreadStart(ScanMonsterInfo);
     MonsterInfoScan    = new Thread(MonsterInfoScanRef)
     {
         Name = $"Scanner_Monster.{MonsterNumber}"
     };
     Debugger.Warn(GStrings.GetLocalizationByXPath("/Console/String[@ID='MESSAGE_MONSTER_SCANNER_INITIALIZED']").Replace("{MonsterNumber}", MonsterNumber.ToString()));
     MonsterInfoScan.Start();
 }
    private void Initialize(string mapName = null)
    {
        MapEntityInfo mei = null;
        GameObject    g   = GameObject.Find("MapEntityInfo");

        if (g != null)
        {
            mei = g.GetComponent <MapEntityInfo>();
            if (mei != null)
            {
                map           = mei.map;
                enemies       = mei.enemies;
                interactables = mei.interactables;
            }
        }
        bool mapAutoGeneration = false;

        if (mapName != null)
        {
            map.mapName       = mapName;
            mapAutoGeneration = true;
            MapInfo mi = MapManager.mm.FindMapInfo(mapName, mapLevel);
            map.GetComponent <AudioSource>().clip = Resources.Load("Audios/" + StringManager.ToPascalCase(mi.backgroundMusic), typeof(AudioClip)) as AudioClip;
            map.GetComponent <AudioSource>().Play();
            monsterNumberMark.SetActive(true);
            monsterNumberText.gameObject.SetActive(true);
            turnLimit  = mi.turnLimit;
            turnNumber = 0;
            if (turnLimit >= 0)
            {
                Canvas.GetComponent <UIInfo>().turnLimitMark.SetActive(true);
                Canvas.GetComponent <UIInfo>().turnLimitText.gameObject.SetActive(true);
                Canvas.GetComponent <UIInfo>().turnLimitText.text = RemainedTurn.ToString();

                int ind = Canvas.GetComponent <UIInfo>().turnLimitSprites.Count - 1;
                if (turnLimit == 0)
                {
                    ind = 0;
                }

                Canvas.GetComponent <UIInfo>().turnLimitMark.GetComponent <Image>().sprite =
                    Canvas.GetComponent <UIInfo>().turnLimitSprites[ind];
                Canvas.GetComponent <UIInfo>().turnLimitMark.GetComponent <Image>().color =
                    Canvas.GetComponent <UIInfo>().turnLimitColors[ind];
                Canvas.GetComponent <UIInfo>().turnLimitText.color =
                    Canvas.GetComponent <UIInfo>().turnLimitColors[ind];
            }
            else
            {
                Canvas.GetComponent <UIInfo>().turnLimitMark.SetActive(false);
                Canvas.GetComponent <UIInfo>().turnLimitText.gameObject.SetActive(false);
            }
        }
        else
        {
            monsterNumberMark.SetActive(false);
            monsterNumberText.gameObject.SetActive(false);
            turnNumber = 0;
            turnLimit  = -1;
            Canvas.GetComponent <UIInfo>().turnLimitMark.SetActive(false);
            Canvas.GetComponent <UIInfo>().turnLimitText.gameObject.SetActive(false);
        }
        hasShopVisited = false;
        StringManager.sm.RefreshTexts();
        map.Initialize(mapAutoGeneration);

        AvailableTile availableTile = new AvailableTile(map.MapSize, map.BottomLeft);    // 맵의 각 타일 위에 새 개체를 놓을 수 있는지 확인

        for (int i = (int)map.BottomLeft.x; i <= (int)map.TopRight.x; i++)
        {
            for (int j = (int)map.BottomLeft.y; j <= (int)map.TopRight.y; j++)
            {
                // 밟을 수 없는 타일 확인
                if (map.GetTypeOfTile(i, j) != 0)
                {
                    availableTile.Set(i, j);
                }
            }
        }

        // 플레이어 시작 위치 지정
        int        randomQuadrant = Random.Range(1, 5);
        Vector2Int v = map.GetACornerPosition(randomQuadrant);

        if (!mapAutoGeneration && SceneManager.GetActiveScene().name.Equals("Tutorial"))
        {
            player.GetComponent <Transform>().position = new Vector3(0f, 0f, -1f);
            map.AddItemOnTile(100, new Vector3(21f, 1f, -1f));
            map.AddItemOnTile(101, new Vector3(21f, 0f, -1f));
            map.AddItemOnTile(102, new Vector3(20f, 0f, -1f));
            map.AddItemOnTile(103, new Vector3(20f, 1f, -1f));
        }
        else if (!mapAutoGeneration && SceneManager.GetActiveScene().name.Equals("Town"))
        {
            player.GetComponent <Transform>().position = new Vector3(2f, 2f, -1f);
            if (isTutorialSkipped)
            {
                map.AddItemOnTile(100, new Vector3(2f, 1f, -1f));
                map.AddItemOnTile(101, new Vector3(2f, 3f, -1f));
                map.AddItemOnTile(102, new Vector3(1f, 2f, -1f));
                map.AddItemOnTile(103, new Vector3(3f, 2f, -1f));
                isTutorialSkipped = false;
            }
        }
        else
        {
            player.GetComponent <Transform>().position =
                new Vector3(v.x, v.y, player.GetComponent <Transform>().position.z);
        }
        map.SetEntityOnTile(player, player.GetComponent <Transform>().position);
        availableTile.Set(v.x, v.y);

        #region MapEntityInfo에 따라 씬에 미리 배치되어 있는 개체 등록
        foreach (Interactable i in mei.interactables)
        {
            map.SetEntityOnTile(i, i.GetComponent <Transform>().position);
            availableTile.Set(i.GetComponent <Transform>().position);
        }
        // TODO 시작 시에 존재하는 모든 적의 충돌 판정 크기가 타일 1개 크기라고 가정
        //      또한, 다른 개체와 같은 타일에 겹쳐 있는 상태로 시작하는 적이 없다고 가정
        //      그리고 맵의 범위를 벗어난 위치에 있거나 벗어난 위치를 순찰 체크포인트로 갖는 적이 없다고 가정
        foreach (Character c in mei.enemies)
        {
            map.SetEntityOnTile(c, c.GetComponent <Transform>().position);
            c.statusUI = UIObject.GetComponent <UIInfo>().enemyStatusUI;
            availableTile.Set(c.GetComponent <Transform>().position);
            foreach (Vector3 cp in ((EnemyMover)c.Mover).checkpoints)
            {
                availableTile.Set(cp);
            }
        }
        #endregion

        #region 맵 정보(MapInfo)에 따라 개체 생성 후 등록
        if (mapName != null)
        {
            MapInfo mi = MapManager.mm.FindMapInfo(mapName, mapLevel);
            if (mi != null)
            {
                foreach (int id in mi.interactablesID)
                {
                    Interactable i = GetComponent <InteractableManager>().GetInteractable(id);
                    if (i != null)
                    {
                        int  quadrant  = 0;
                        int  maxLoop   = 100;
                        bool canCreate = true;
                        for (int j = 0; j < maxLoop; j++)
                        {
                            if (id == 0)
                            {
                                for (int k = 0; k < maxLoop; k++)
                                {
                                    quadrant = Random.Range(1, 5);
                                    if (quadrant != randomQuadrant)
                                    {
                                        break;
                                    }
                                    if (k == maxLoop - 1)
                                    {
                                        Debug.LogWarning("Exceed max loop limit!");
                                    }
                                }
                                //v = map.GetACornerPosition((randomQuadrant + 2) % 4);
                                v = map.GetACornerPosition(quadrant);
                                if (map.GetEntityOnTile(v.x, v.y) == null && map.GetTypeOfTile(v.x, v.y) == 0)
                                {
                                    break;
                                }
                            }
                            else
                            {
                                v = new Vector2Int(Random.Range(Mathf.RoundToInt(map.BottomLeft.x), Mathf.RoundToInt(map.TopRight.x)),
                                                   Random.Range(Mathf.RoundToInt(map.BottomLeft.y), Mathf.RoundToInt(map.TopRight.y)));
                                if (map.GetEntityOnTile(v.x, v.y) == null && map.GetTypeOfTile(v.x, v.y) == 0)
                                {
                                    break;
                                }
                            }
                            if (j == maxLoop - 1)
                            {
                                Debug.LogWarning("Exceed max loop limit!");
                                canCreate = false;
                            }
                        }
                        if (!canCreate)
                        {
                            continue;
                        }

                        // TODO 생성 위치 바꾸기
                        g = Instantiate(i.gameObject, new Vector3(v.x, v.y, -1f), Quaternion.identity);
                        interactables.Add(g.GetComponent <Interactable>());
                        map.SetEntityOnTile(g.GetComponent <Interactable>(), g.GetComponent <Transform>().position);
                        availableTile.Set(v.x, v.y);
                    }
                }
                // TODO 맵 정보에 의해 생성되는 모든 적의 충돌 판정 크기가 타일 1개 크기라고 가정
                //      또한, 다른 개체와 같은 타일에 겹쳐 있는 상태로 시작하는 적이 없다고 가정
                foreach (int id in mi.enemiesID)
                {
                    EnemyInfo ei = EnemyManager.em.FindEnemyInfo(id);
                    if (ei != null)
                    {
                        // 생성 위치 정하기
                        int  x = 0, y = 0, x2 = 0, y2 = 0, maxLoop = 100;
                        bool canCreate = true;
                        for (int j = 0; j < maxLoop; j++)
                        {
                            // 우선 가능한 위치 중에서 랜덤으로 생성하고, 후에 스폰 가능한 위치인지 확인
                            x = Random.Range(Mathf.RoundToInt(map.BottomLeft.x), Mathf.RoundToInt(map.TopRight.x));
                            y = Random.Range(Mathf.RoundToInt(map.BottomLeft.y), Mathf.RoundToInt(map.TopRight.y));
                            if (map.GetEntityOnTile(x, y) == null && map.GetTypeOfTile(x, y) == 0 && availableTile.Get(x, y) &&
                                VectorUtility.ChebyshevDistance(new Vector3(x, y, 0f), player.GetComponent <Transform>().position) > 3)
                            {
                                bool b = true;
                                foreach (Interactable i in interactables)
                                {
                                    if (VectorUtility.ChebyshevDistance(new Vector3(x, y, 0f), i.GetComponent <Transform>().position) <= 2)
                                    {
                                        b = false;
                                        break;
                                    }
                                }
                                if (b)
                                {
                                    // 순찰 경로 지정
                                    if (ei.type == EnemyInfo.Type.Normal || (mapLevel >= 64 && ei.type == EnemyInfo.Type.Elite))
                                    {
                                        int  distance = 4;
                                        bool b2       = true;
                                        for (int k = 0; k < maxLoop; k++)
                                        {
                                            // 자신 근처의 위치 중에서, 순찰 경로 안에 스폰 불가능 위치가 하나도 존재하지 않은 위치로 결정
                                            // 순찰 경로의 체크포인트가 하나만 존재함을 가정
                                            x2 = Random.Range(Mathf.Clamp(x - distance, 0, map.MapSize.x - 1), Mathf.Clamp(x + distance, 0, map.MapSize.x - 1));
                                            y2 = Random.Range(Mathf.Clamp(y - distance, 0, map.MapSize.y - 1), Mathf.Clamp(y + distance, 0, map.MapSize.y - 1));
                                            if (map.GetEntityOnTile(x2, y2) == null && map.GetTypeOfTile(x2, y2) == 0 && !(x2 == x && y2 == y))
                                            {
                                                bool b3 = true;
                                                for (int l = Mathf.Min(x, x2); l <= Mathf.Max(x, x2); l++)
                                                {
                                                    if (!availableTile.Get(l, Mathf.Min(y, y2)) || !availableTile.Get(l, Mathf.Max(y, y2)))
                                                    {
                                                        b3 = false;
                                                        break;
                                                    }
                                                }
                                                for (int l = Mathf.Min(y, y2); l <= Mathf.Max(y, y2); l++)
                                                {
                                                    if (!availableTile.Get(Mathf.Min(x, x2), l) || !availableTile.Get(Mathf.Max(x, x2), l))
                                                    {
                                                        b3 = false;
                                                        break;
                                                    }
                                                }
                                                if (b3)
                                                {
                                                    break;
                                                }
                                            }
                                            if (k == maxLoop - 1)
                                            {
                                                //Debug.LogWarning("Exceed max loop limit!");
                                                b2 = false;
                                            }
                                        }
                                        if (b2)
                                        {
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                            if (j == maxLoop - 1)
                            {
                                Debug.LogWarning("Exceed max loop limit!");
                                canCreate = false;
                            }
                        }
                        if (!canCreate)
                        {
                            continue;
                        }

                        g = Instantiate(EnemyManager.em.monsterPrefab, new Vector3(x, y, -1f), Quaternion.identity);
                        Character c = g.GetComponent <Character>();
                        c.name  = ei.name;
                        c.level = mapLevel;
                        //Debug.Log("GM creates an enemy. (call first)");
                        enemies.Add(c);
                        map.SetEntityOnTile(c, g.GetComponent <Transform>().position);
                        c.statusUI = UIObject.GetComponent <UIInfo>().enemyStatusUI;
                        availableTile.Set(x, y);

                        c.GetComponent <EnemyMover>().checkpoints = new List <Vector3>();

                        if (ei.type == EnemyInfo.Type.Normal || (mapLevel >= 64 && ei.type == EnemyInfo.Type.Elite))
                        {
                            c.GetComponent <EnemyMover>().checkpoints.Add(new Vector3(x2, y2, -1f));
                            availableTile.Set(x2, y2);
                            for (int l = Mathf.Min(x, x2); l <= Mathf.Max(x, x2); l++)
                            {
                                availableTile.Set(l, y);
                                availableTile.Set(l, y2);
                            }
                            for (int l = Mathf.Min(y, y2); l <= Mathf.Max(y, y2); l++)
                            {
                                availableTile.Set(x, l);
                                availableTile.Set(x2, l);
                            }
                        }
                    }
                }
            }
        }
        #endregion

        monsterNumberText.text = MonsterNumber.ToString();
        if (MonsterNumber == 0)
        {
            monsterNumberText.color = ColorManager.cm.monsterNumberColors[0];
        }
        else
        {
            monsterNumberText.color = ColorManager.cm.monsterNumberColors[1];
        }
        if (mapAutoGeneration)
        {
            monsterEliminated = false;
        }
        else
        {
            monsterEliminated = true;
        }
    }