// *********************************************************************** // Assembly : Game // Author : Kimch // Created : 2020-09-12 // Description : // Last Modified By : // Last Modified On : // *********************************************************************** // // // *********************************************************************** using System.Collections; using System.Collections.Generic; using CodeStage.AntiCheat.ObscuredTypes; using F.ObjectPool; using UnityEngine; namespace G { /// /// 游戏模式 /// partial class GameLevel : MonoBehaviour { #region Field public const int MAX_DOOR_COUNT = 1; public const int MAX_PROP_COUNT = 8; public const int MAX_SPAWN_POINT_COUNT = 16; public const string STAGE_POOL_NAME = "stage"; private ItemLevel _curLevelItem; private ItemStage _curStageItem; /// /// /// private ObscuredInt _firstStageIndex; /// /// /// private ObscuredInt _curStageIndex; /// /// /// private ObscuredInt _maxStageIndex; /// /// /// private bool _levelFinish = true; /// /// /// private bool _stageFinish = true; private bool _stageStart = false; private float _startLevelTime; private float _startStageTime; private bool _studyLevelSkill; private bool _studyStageSkill; /// /// 加载状态 /// private int _loadState = 0; /// /// 传送门 /// private readonly GameObject[] _portals = new GameObject[MAX_DOOR_COUNT]; /// /// /// private Transform _stageRoot; /// /// /// private List _spawnPoints = new List(MAX_SPAWN_POINT_COUNT); private Vector3[] _propPoints = new Vector3[MAX_SPAWN_POINT_COUNT]; private Transform _giftBox; /// /// 出生点 /// private Vector3 _bornPoint; /// /// /// private float _timeScale1 = 1f; /// /// 2级加速 /// private float _timeScale2 = 1f; #endregion #region Property /// /// /// public int curChapterId { get => _curLevelItem.chapterId; } /// /// /// public int curLevelId { get => _curLevelItem.id; } /// /// /// public int curStageId { get => _curStageItem.id; } /// /// /// public int reportStageId { get => _curLevelItem.id * 100 + _curStageIndex; } /// /// /// public int curStageIndex => _curStageIndex; /// /// /// public int maxStageIndex => _maxStageIndex; /// /// /// public bool studyLevelSkill => _studyLevelSkill; /// /// /// public bool isBossStage => curStageItem.type == 2; /// /// /// public ItemLevel curLevelItem { get { return _curLevelItem; } } /// /// /// public ItemStage curStageItem { get { return _curStageItem; } } /// /// 1.正常 2.无尽 3.盗贼 4.爬塔 /// public int levelMode { get { return curLevelItem.type; } } /// /// 无尽模式 /// public bool infinityMode { get { return curLevelItem.type == 2; } } /// /// 正常闯关 /// public bool normalMode { get { return curLevelItem.type == 1; } } /// /// /// public bool levelFinish { get { return _levelFinish; } } public GameObject portalAsset { get { return (GameObject)GameScene.Instance.sceneCommonAssets["portal"]; } } public GameObject giftBoxAsset { get { return (GameObject)GameScene.Instance.sceneCommonAssets["gift_box"]; } } /// /// 地图资源名 /// public string mapAssetName { get { var assets = _curLevelItem.assets; if (assets != null && assets.Length > 0) { var index = Mathf.Min(_curStageItem.assetIndex, assets.Length - 1); return assets[index]; } return _curStageItem.assets; } } /// /// /// public int stageBoxId { get { var boxes = curLevelItem.boxes; if (boxes != null && boxes.Length > 0 && _curStageIndex > 0) { if (_curStageIndex < boxes.Length) return boxes[_curStageIndex]; else return boxes[boxes.Length - 1]; } return 0; } } /// /// /// public int stageStartStory { get { var stories = curLevelItem.stories; if (stories != null && _curStageIndex > 0 && _curStageIndex < stories.Length) { if (stories[_curStageIndex] != null && stories[_curStageIndex].Length > 0) return stories[_curStageIndex][0]; } return 0; } } /// /// /// public int stageEndStory { get { var stories = curLevelItem.stories; if (stories != null && _curStageIndex > 0 && _curStageIndex < stories.Length) { if (stories[_curStageIndex] != null && stories[_curStageIndex].Length > 0) return stories[_curStageIndex][1]; } return 0; } } /// /// /// public int stageAdventure { get { if (curStageItem.type == 3) { var stageTypeArgs = curStageItem.typeArgs; if (stageTypeArgs != null && stageTypeArgs.Length > 0) { return stageTypeArgs[0]; } if (Random.value < 0.618f) return 0; } return -1; } } private float _levelFactor = 0f; /// /// /// public float levelFactor { get { switch (this.levelMode) { case 1: if (_levelFactor == 0f) { if (GlobalVar.EnterLevelFactor > 0) { _levelFactor = GlobalVar.EnterLevelFactor; } else { if (curLevelItem.difficulty != null && curLevelItem.difficulty.Length > 0) _levelFactor = curLevelItem.difficulty[0]; } _levelFactor = _levelFactor * 0.01f + 1f; } return _levelFactor * _dynamicDifficult; case 2: return 1f + Mathf.Max(0, _curStageIndex - 100) * 0.08f;//100关以后增加度 default: return 1f; } } } /// /// 战力压制 /// public float difficultyValue { get { float result = 1f; if (levelMode == 1) { float diffCV = PlayerProxy.Instance.combatValue - curLevelItem.requireCV; diffCV = diffCV / Mathf.Clamp(curLevelItem.requireCV, 100000f, 1000000f); diffCV = diffCV * 3f; result = Mathf.Max(1f - diffCV, 0.6f); } else if (levelMode == 4) { var swordLevelItem = ItemProxy.Instance.GetStaticItem(_curStageIndex); if (swordLevelItem != null) { float diffCV = PlayerProxy.Instance.combatValue - swordLevelItem.requirementCV; diffCV = diffCV / Mathf.Clamp(swordLevelItem.requirementCV, 10000f, 1000000f); result = Mathf.Max(1f - diffCV * 6f, 0.6f); } } return result; } } private bool _setStageFactor; private readonly float[] _stageFactor = new float[4]; private readonly float[] _stageFactorB = new float[4]; private float[] stageFactor { get { if (_stageFactor[0] == 0f && _stageFactor[1] == 0f) { var levelFactors = curLevelItem.difficulty; var stageFactors = curStageItem.factor; _stageFactor[0] = stageFactors[0] * 0.01f; _stageFactor[1] = stageFactors[2] * 0.01f; _stageFactor[2] = stageFactors[4] * 0.01f; _stageFactor[3] = stageFactors[6] * 0.01f; _stageFactorB[0] = stageFactors[1]; _stageFactorB[1] = stageFactors[3]; _stageFactorB[2] = stageFactors[5]; _stageFactorB[3] = stageFactors[7]; int mode = this.levelMode; if (mode == 1) { float diffCV = this.difficultyValue * _dynamicDifficult; #if UNITY_EDITOR Debug.Log("战力压制 " + diffCV); #endif _stageFactor[0] *= (levelFactors[0] * 0.01f + 1f); _stageFactor[1] *= (levelFactors[1] * 0.01f + 1f); _stageFactor[2] *= (levelFactors[2] * 0.01f + 1f) * diffCV; _stageFactor[3] *= (levelFactors[3] * 0.01f + 1f) * diffCV; } else if (mode == 4) { float diffCV = this.difficultyValue * _dynamicDifficult; #if UNITY_EDITOR Debug.Log("战力压制 " + diffCV); #endif _stageFactor[0] *= diffCV; _stageFactor[1] *= diffCV; _stageFactor[2] *= diffCV; _stageFactor[3] *= diffCV; } else if (mode == 2) { var f = 1f + Mathf.Max(0, _curStageIndex - 100) * 0.08f;//100关以后增加度) _stageFactor[0] *= f; _stageFactor[1] *= f; _stageFactor[2] *= f; _stageFactor[3] *= f; } } return _stageFactor; } } /// /// /// public float[] stageFactorA { get { return stageFactor; } } /// /// /// public float[] stageFactorB { get { return _stageFactorB; } } /// /// 游戏速度 /// public float gameSpeed { get { return _timeScale1; } set { _timeScale1 = value; } } /// /// /// public Vector3 endPosition { get; private set; } /// /// /// public bool supportRampage { get { return stageMode != GameMode.Limit && stageMode != GameMode.Escort; } } private int _rampageTime = 999999; /// /// 是否暴走 /// public bool isRampage { get { return supportRampage && _spawnStartTime > _rampageTime; } } /// /// 进入暴走剩余时间 /// public int rampageTime => (int)(_rampageTime - _spawnStartTime); /// /// 场景灯光 /// public Light stageMainLight { get; private set; } #endregion #region Method /// /// 进入场景 /// public void OnEnterScene() { GlobalNotifier.PostNotification(GlobalDefine.EVENT_LEVEL_SCENE, type: "enter"); AssetProxy.Instance.CreateReleasePool(STAGE_POOL_NAME); StartLevel(GlobalVar.EnterLevelId, GlobalVar.EnterStageIndex); } /// /// 离开场景 /// public void OnExitScene() { AssetProxy.Instance.RemoveReleasePool(STAGE_POOL_NAME); GlobalNotifier.PostNotification(GlobalDefine.EVENT_LEVEL_SCENE, type: "exit"); } /// /// 开始关卡 /// /// public void StartLevel(int levelId, int stageIndex) { _curLevelItem = ItemProxy.Instance.GetStaticItem(levelId); _firstStageIndex = Mathf.Max(1, stageIndex); _levelFinish = false; _startLevelTime = Time.unscaledTime; _studyLevelSkill = false; if (_curLevelItem != null) { LoadLevel(); _curStageIndex = 1; _maxStageIndex = _curLevelItem.maxStage; var stageId = GlobalUtils.GetRandom(_curLevelItem.startStage); //计算 while (_curStageIndex < stageIndex && _curStageIndex < _maxStageIndex) { var stageItem = ItemProxy.Instance.GetStaticItem(stageId); if (_curStageIndex < _maxStageIndex - 1) { stageId = GlobalUtils.GetRandom(stageItem.nextStages); if (stageId <= 0) { stageId = GlobalUtils.GetRandom(curLevelItem.endStage); } _curStageIndex++; } else { stageId = GlobalUtils.GetRandom(curLevelItem.endStage); if (stageId <= 0) { stageId = GlobalUtils.GetRandom(stageItem.nextStages); } _curStageIndex = _maxStageIndex; } } StartStage(stageId); } #if UNITY_EDITOR else { Debug.LogError("关卡配置表错误"); } #endif InitBattleResult(); } /// /// /// /// public void FinishLevel(bool success, string reason) { if (!_levelFinish) { if (success) { GlobalNotifier.PostNotification(GlobalDefine.EVENT_LEVEL_STATE, null, "finish"); } _levelFinish = true; SetLevelResult(success, (int)(Time.unscaledTime - _startLevelTime), reason); } } /// /// 加载通用资源 /// private void LoadLevel() { var assets = GameScene.Instance.sceneCommonAssets; _loadState = 1; } /// /// /// public void UnloadLevel() { StopSpawn(); EntityManager.Instance.RemoveAllEntity(); } public void StartStage(int stageId) { _stageFinish = false; _startStageTime = Time.time; _studyStageSkill = false; for (int i = 0; i < _stageFactor.Length; i++) { _stageFactor[i] = 0f; } _curStageItem = ItemProxy.Instance.GetStaticItem(stageId); if (_curStageItem != null) { if (_curStageItem.type == 1 || _curStageItem.type == 3) _rampageTime = GlobalProxy.Instance.GetInt(6); else if (_curStageItem.type == 2) { _rampageTime = GlobalProxy.Instance.GetInt(7); } SetMode(_curStageItem.type); SetGroundText("", 0, 0); LoadStage(true); StartStage(); KStatistics.Instance.ReportEventStartStage(reportStageId.ToString()); } else { Debug.LogError("关卡配置错误."); } } /// /// 进入当前关 /// public void LoadStage(bool clear) { if (clear) { this.UnloadStage(); _loadState = 1; } else { _loadState = 2; } StartCoroutine(LoadStageCO(mapAssetName)); } /// /// /// /// public IEnumerator LoadStageCO(string mapAsset) { while (_loadState == 0) { yield return null; } if (_stageRoot && _stageRoot.name != mapAsset) { Destroy(_stageRoot.gameObject); _stageRoot = null; } if (!_stageRoot) { var handle = AssetProxy.Instance.TryGetAssetAsync(mapAsset, STAGE_POOL_NAME); yield return handle; _stageRoot = Instantiate(handle.Result, Vector3.zero, Quaternion.identity).transform; _stageRoot.name = mapAsset; var lights = Light.GetLights(LightType.Directional, 2); if (lights != null && lights.Length > 0) { if (SettingProxy.Instance.lowEffect) { lights[0].cookie = null; } stageMainLight = lights[0]; } InitPoint(); _loadState = 2; } InitPortal(); InitGiftBox(); _loadState = 3; //// LoadStageCompleted(); } /// /// /// private void LoadStageCompleted() { if (UI.GameWindow.Instance == null || !UI.GameWindow.Instance.gameObject || !UI.GameWindow.Instance.gameObject.activeSelf) KUIWindow.OpenWindow(); //加个事件 } /// /// 清理关卡数据 /// private void UnloadStage() { //清理传送门 for (int i = 0; i < _portals.Length; i++) { SpawnPool.Despawn(_portals[i]); _portals[i] = null; } //清理道具 if (EntityManager.Instance) { EntityManager.Instance.RemoveAllProp(); } EnemyHelper.Instance.GetComponent().FinishEfs(); UI.QuickBox.Clear(); } /// /// /// public void StartStage() { StartCoroutine(StartStageCO()); UpdateBattleResult(); if (_curStageIndex > _firstStageIndex) { if (this.normalMode) { //SaveNormalLevelState(); } else if (this.infinityMode) { SaveEndlessLevelState(); } else if (this.levelMode == 4) { SaveClimbLevelState(); EntityMainPlayer.Instance.curHp = EntityMainPlayer.Instance.maxHp; } } } private IEnumerator StartStageCO() { //等游戏ui while (UI.GameWindow.Instance == null || !UI.GameWindow.Instance.isRegister) { yield return null; } //剧情 if (!_curLevelItem.isCompleted) { var storyId = stageStartStory; if (storyId > 0) { var storying = false; storying = StoryProxy.Instance.TriggerStory(storyId, () => { storying = false; }); while (storying) { yield return null; } } } // 学习关卡技能 if (!_studyLevelSkill) { var autoStudySkill = EntityMainPlayer.Instance.autoStudySkill; if (_curStageIndex > 1) { if (infinityMode) { MovesShop.Instance.SetMultiMovesPackage(curLevelItem.skillCardPackage[0], Mathf.Clamp(_curStageIndex - 1, 0, 100) / 5 + 1, this.OnStudyLevelSkill); } else { LoadNormalLevelState(); _studyLevelSkill = true; } } else if (curLevelItem.skillCardPoint > 0) { MovesShop.Instance.SetMovesPackage(curLevelItem.skillCardPackage[curLevelItem.isCompleted ? 1 : 0], autoStudySkill, (error, message) => { _studyLevelSkill = true; }); } else { _studyLevelSkill = true; } while (!_studyLevelSkill) { yield return null; } if (autoStudySkill) { yield return new WaitForSeconds(1f); } } // 学习路段技能 if (!_studyStageSkill) { if (curStageItem.skillCardPackage > 0 && curStageItem.skillCardPoint > 0) { var autoStudySkill = EntityMainPlayer.Instance.autoStudySkill; MovesShop.Instance.AddMovesPoint(curStageItem.skillCardPoint); MovesShop.Instance.SetMovesPackage(curStageItem.skillCardPackage, autoStudySkill, (error, message) => { _studyStageSkill = true; }); while (!_studyStageSkill) { yield return null; } if (autoStudySkill) { yield return new WaitForSeconds(1f); } } else { _studyStageSkill = true; } } // 奇遇 if (!_curLevelItem.isCompleted) { int adventureId = stageAdventure; if (adventureId >= 0) { var autoSelect = EntityMainPlayer.Instance.autoSelectAdventure; var showing = true; showing = AdventureProxy.Instance.ShowStageAdventure(adventureId, autoSelect, () => { showing = false; }); while (showing) { yield return null; } } } while (_loadState < 3) { yield return null; } //进入开场 while (!EntityMainPlayer.Instance.EnterScene(_bornPoint)) { yield return null; } //开场特效 UI.ToastBox.ShowText($"第{_curStageIndex}关", 6); //GlobalNotifier.PostNotification(GlobalDefine.EVENT_SHOW_EFFECT, "20681_", ""); if (curStageItem.skillCardPackage > 0 && MovesShop.Instance.totalMovesPoint > 0) GlobalNotifier.PostNotification(GlobalDefine.EVENT_SHOW_LVUP_EFFECT, MovesShop.Instance.totalMovesPoint + 1, ""); yield return new WaitForSeconds(0.8f); GlobalNotifier.PostNotification(GlobalDefine.EVENT_STAGE_STATE, curStageItem, "start"); StartSpawn(); } /// /// /// /// private void OnStudyLevelSkill(int error, string message) { _studyLevelSkill = true; } /// /// /// /// private void OnStudyStageSkill(int error) { _studyStageSkill = true; } /// /// 结束当前关卡 /// public void FinishStage(bool success = true) { if (!_stageFinish) { _stageFinish = true; StopSpawn(); StartCoroutine(FinishStageCO(success)); } } /// /// /// /// private IEnumerator FinishStageCO(bool success) { if (success) { UI_Ingame.Instance.ShowEffect("UI_fx_Repel"); } else { UI_Ingame.Instance.ShowEffect("UI_fx_BattleFail"); } //GlobalNotifier.PostNotification(GlobalDefine.EVENT_SHOW_EFFECT, "20839_", "finish"); yield return null; if (!_curLevelItem.isCompleted && stageEndStory > 0) { var storying = false; storying = StoryProxy.Instance.TriggerStory(stageEndStory, () => { storying = false; }); while (storying) { yield return null; } } if (success && stageBoxId > 0) { Vector3 vector = EntityMainPlayer.Instance.position * Random.Range(0.7f, 0.85f); OpenGiftBox(vector); } else { OpenPortal(1f); } GlobalNotifier.PostNotification(GlobalDefine.EVENT_STAGE_STATE, curStageItem, "finish"); } /// /// 下一小关 /// public void NextStage() { if (_curStageIndex < _maxStageIndex - 1) { var nextStageId = GlobalUtils.GetRandom(curStageItem.nextStages); if (nextStageId <= 0) { nextStageId = GlobalUtils.GetRandom(curLevelItem.endStage); } _curStageIndex++; StartStage(nextStageId); } else { var nextStageId = GlobalUtils.GetRandom(curLevelItem.endStage); if (nextStageId <= 0) { nextStageId = GlobalUtils.GetRandom(curStageItem.nextStages); } _curStageIndex = _maxStageIndex; StartStage(nextStageId); } } /// /// /// private void InitPoint() { _spawnPoints.Clear(); var spawnRoot = _stageRoot.Find("aaapoint"); if (spawnRoot) for (int i = spawnRoot.childCount - 1; i >= 0; i--) { _spawnPoints.Add(spawnRoot.GetChild(i).position); } var propRoot = _stageRoot.Find("bbbpoint"); if (propRoot) for (int i = 0; i < MAX_PROP_COUNT; i++) { _propPoints[i] = propRoot.GetChild(i).position; } var bornPointT = _stageRoot.Find("born_point"); _bornPoint = bornPointT ? bornPointT.position : Vector3.zero; var doorT = _stageRoot.Find("door1"); endPosition = doorT ? doorT.position : new Vector3(0f, 0f, 4f); } private void InitGiftBox() { if (!_giftBox) _giftBox = Instantiate(giftBoxAsset.transform, Vector3.up * 60f, Quaternion.Euler(0f, 30f, 0f)); _giftBox.transform.position = Vector3.up * 60f; _giftBox.gameObject.SetActive(false); } /// /// /// private void InitPortal() { if (_curStageIndex == _maxStageIndex) { for (int i = 0; i < _portals.Length; i++) { CreatePortal(i, ""); } } else if (_curStageIndex < _maxStageIndex) { //var nextStageId = curStageItem.l if (_curStageIndex == _maxStageIndex - 1 && curLevelItem.hasEnd) { for (int i = 0; i < _portals.Length; i++) { CreatePortal(i, "portal_boss"); } } else { for (int i = 0; i < _portals.Length; i++) { var nextIndex = GlobalUtils.GetRandom(curStageItem.nextStages); CreatePortal(i, $"portal_{nextIndex}"); } } } } /// /// /// private void CreatePortal(int index, string doorName) { var doorRoot = _stageRoot.Find($"door{index + 1}"); if (doorRoot) { if (!_portals[index]) _portals[index] = SpawnPool.Spawn(portalAsset, doorRoot.position, doorRoot.rotation); _portals[index].SetActive(false); _portals[index].name = doorName; } } /// /// /// /// public void OpenGiftBox(Vector3 position) { if (this.normalMode) { SaveNormalLevelState(); } _giftBox.position = position; _giftBox.gameObject.SetActive(true); } /// /// 打开传送门 /// public void OpenPortal(float delay = 3.6f) { if (_curStageIndex < _maxStageIndex) { StartCoroutine(OpenPortalCO(delay)); } else { FinishLevel(true, ""); } } /// /// /// /// /// private IEnumerator OpenPortalCO(float delay) { yield return new WaitForSeconds(delay); for (int i = 0; i < _portals.Length; i++) { _portals[i].SetActive(true); } } public void SetGroundText(string text, float duration, float delay) { //if (_textMesh) StartCoroutine(SetTextCO(text, delay)); } private IEnumerator SetTextCO(string text, float delay) { yield return new WaitForSeconds(delay); //_textMesh.text = text; } private void UpdateTimeScale() { if (!_stageFinish) { if (Time.timeScale >= 1f) { Time.timeScale = gameSpeed; } } else { if (Time.timeScale > 1f) { Time.timeScale = 1f; } } } #endregion #region Diffcult private float _dynamicDifficult; public void AddDifficult() { _dynamicDifficult = Mathf.Clamp(_dynamicDifficult + 0.025f, 0.9f, 1.1f); ArchiveProxy.Instance.GetInt("difficult", Mathf.FloorToInt(_dynamicDifficult * 100)); } public void ReduceDifficult() { _dynamicDifficult = Mathf.Clamp(_dynamicDifficult - 0.1f, 0.9f, 1.1f); ArchiveProxy.Instance.GetInt("difficult", Mathf.FloorToInt(_dynamicDifficult * 100)); } #endregion #region Setting private bool _trackEnemy = true; public bool autoTrackEnemy { get => _trackEnemy; set { if (_trackEnemy != value) { _trackEnemy = value; PlayerPrefs.SetInt("track_enemy", value ? 1 : 0); PlayerPrefs.Save(); } } } private bool _vibrateSwitch = false; public bool vibrateSwitch { get => _vibrateSwitch; set { if (_vibrateSwitch != value) { _vibrateSwitch = value; PlayerPrefs.SetInt("vibrate_switch", value ? 1 : 0); PlayerPrefs.Save(); } } } private void InitSetting() { _trackEnemy = PlayerPrefs.GetInt("track_enemy", 1) != 0; _vibrateSwitch = PlayerPrefs.GetInt("vibrate_switch", 0) != 0; } #endregion #region Unity public static GameLevel Instance; private void Awake() { Instance = this; _dynamicDifficult = Mathf.Clamp(ArchiveProxy.Instance.GetInt("difficult", 100) * 0.01f, 0.8f, 1.2f); OnEnterScene(); InitSetting(); } private void OnDestroy() { OnExitScene(); PlayerProxy.Instance.TryoutFinish(); } private void Update() { if (!_stageFinish) { UpdateMode(); UpdateSpawn(); } #if UNITY_EDITOR if (Input.GetKeyUp(KeyCode.LeftArrow)) { gameSpeed -= 0.5f; } else if (Input.GetKeyUp(KeyCode.RightArrow)) { gameSpeed += 0.5f; } else if (Input.GetKeyUp(KeyCode.Space)) { gameSpeed = 1f; } else if (Input.GetKeyUp(KeyCode.UpArrow)) { gameSpeed = 0f; MovesShop.Instance.AddMovesPoint(curStageItem.skillCardPoint); MovesShop.Instance.SetMovesPackage(curStageItem.skillCardPackage, false, (error, message) => { gameSpeed = 1f; }); } #endif } private void LateUpdate() { UpdateTimeScale(); } #endregion } }