using System; using System.Linq; using game; using UnityEditor; using UnityEngine; using Object = UnityEngine.Object; public class CheatsWindow : EditorWindow { private bool FreezeLevel { get { return _freezeLevel; } set { _freezeLevel = value; G.DebugFreezeLevel = value; } } private static CheatsWindow _instance = null; private static Configs _configs = null; private static GameData _save = null; private static DataGame _original = null; private static DataGame _custom = null; private static bool _safeModeForSequence = false; private bool _freezeLevel; public static bool IsVisible => _instance != null; public static void Open() { _instance = (CheatsWindow)GetWindow(typeof(CheatsWindow)); _instance.titleContent.text = "Cheats"; _instance.Show(); } private void OnEnable() { if (_instance == null) _instance = this; Load(); G.DebugFreezeLevel = _freezeLevel; } public static new void Close() { ((EditorWindow) _instance).Close(); _instance = null; } private static void Load() { _save = new GameData(Settings.VERSION); _save.UnregisterPersistentStructures(); _save.TryLoadOrCreateNew(); _original = _save.DevGetState(); _custom = (DataGame)_original.clone(); LoadConfigs(); LoadGameSettings(); } private static void LoadConfigs() { var asset = Resources.Load("ext_config/configs/packed_bundle"); (_configs = new Configs()).Load(new System.IO.MemoryStream(asset.bytes)); } private static void LoadGameSettings() { var levels = _configs.Get("@game_levels"); var buffs = _configs.Get("@game_buffs"); GameSettings.Load(levels, buffs); } private void OnGUI() { Render(); } private void Render() { EditorGUILayout.BeginHorizontal(); TabOfCurrentData(); TabOfSettings(); EditorGUILayout.EndHorizontal(); Sequence(); Buttons(); TabOfHotkeys(); } private static void TabOfCurrentData() { EditorGUILayout.BeginVertical(GUI.skin.box); Title("Original"); GUILayout.Label($"Completed: {_original.progress.completed}"); int coinsItem = _original.inventory.purchased.FindIndex(i => i.protoId == EnumConsumable.COIN.GetItemID()); uint coinsAmount = _original.inventory.purchased.HasIndex(coinsItem) ? _original.inventory.purchased[coinsItem].amount : 0; GUILayout.Label($"Coins: {coinsAmount}"); EditorGUILayout.EndVertical(); } private static void Title(string text) { GUILayout.Label(text, new GUIStyle(EditorStyles.label) { alignment = TextAnchor.MiddleCenter, margin = new RectOffset(0, 0, 12, 6), fontSize = 16 }); } private void TabOfSettings() { EditorGUILayout.BeginVertical(GUI.skin.box); Title("Custom"); EditorGUILayout.BeginHorizontal(); CompletedInput(); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label("Coins:", GUILayout.ExpandWidth(false)); int coinsItemIndex = _custom.inventory.purchased.FindIndex(c => c.protoId == EnumConsumable.COIN.GetItemID()); if (_custom.inventory.purchased.HasIndex(coinsItemIndex) == false) { _custom.inventory.purchased.Add(new DataItem { amount = 0, protoId = EnumConsumable.COIN.GetItemID()}); coinsItemIndex = _custom.inventory.purchased.FindIndex(c => c.protoId == EnumConsumable.COIN.GetItemID()); } DataItem coinsItem = _custom.inventory.purchased[coinsItemIndex]; coinsItem.amount = (uint)EditorGUILayout.IntField((int)coinsItem.amount); _custom.inventory.purchased[coinsItemIndex] = coinsItem; EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); GUILayout.Label($"Safe Mode:", GUILayout.ExpandWidth(false)); _safeModeForSequence = GUILayout.Toggle(_safeModeForSequence, ""); GUILayout.Label($"Freeze level:", GUILayout.ExpandWidth(false)); FreezeLevel = GUILayout.Toggle(FreezeLevel, ""); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); } private static void CompletedInput() { GUILayout.Label("Completed: ", GUILayout.ExpandWidth(false)); var completedInput = (uint)EditorGUILayout.IntField((int)_custom.progress.completed); if (completedInput == _custom.progress.completed) return; if (_safeModeForSequence) { _custom.progress.completed = (uint)Mathf.Min(completedInput, _custom.progress.sequence.Count - 1); GUI.FocusControl(null); } else { _custom.progress.completed = completedInput; } var defaultSequenceLenght = GameSettings.Levels.DefaultSequence.Count + GameSettings.Levels.TutorialLenght; var sequenceMustBeDefault = completedInput < defaultSequenceLenght; if (sequenceMustBeDefault) { _custom.progress.sequence = SequenceBuilder.BuildDefaultWithTutorial(); _custom.progress.position = completedInput; } else { var outOfSequence = completedInput > _custom.progress.sequence.Count; if (outOfSequence) { _custom.progress.position = 0; _custom.progress.sequence = SequenceBuilder.BuildByPattern(GameSettings.Levels.GetRandomPattern()); } else { _custom.progress.position = completedInput; } } } private void Sequence() { EditorGUILayout.BeginVertical(GUI.skin.box); Title("Sequence"); EditorGUILayout.BeginHorizontal(); if (_custom.progress.sequence.IsEmpty()) _custom.progress.sequence = SequenceBuilder.BuildDefaultWithTutorial(); var sequence = _custom.progress.sequence; var buttonsStyle = GetLevelButtonStyle(); var bonusLevels = GameSettings.Levels.GetIDsBy(l => l.Type == EnumLevelType.TUTORIAL); var bossLevels = GameSettings.Levels.GetIDsBy(l => l.Type == EnumLevelType.BOSS); const int itemsPerLine = 10; for (int i = 0; i < sequence.Count; i++) { if (_custom.progress.position == i) { buttonsStyle.normal.background = CreateTexture(Color.red); } else { if (bonusLevels.Contains(sequence[i])) buttonsStyle.normal.background = CreateTexture(new Color(0, 0.2f, 0)); else if (bossLevels.Contains(sequence[i])) buttonsStyle.normal.background = CreateTexture(new Color(0.2f, 0.2f, 0)); else buttonsStyle.normal.background = CreateTexture(Color.black); } if (GUILayout.Button($"{sequence[i]}", buttonsStyle)) { _custom.progress.position = (uint) i; _custom.progress.completed = (uint) Mathf.Max(0, i - _original.progress.completed); } if ((i + 1) % itemsPerLine == 0) { EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); } } EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); } private static GUIStyle GetLevelButtonStyle() { var button = new GUIStyle(EditorStyles.label) { alignment = TextAnchor.MiddleCenter, margin = new RectOffset(0, 0, 12, 6), fontSize = 12, normal = {textColor = Color.white} }; return button; } private static Texture2D CreateTexture(Color color) { var texture = new Texture2D(1, 1); texture.SetPixel(1, 1, color); texture.Apply(); return texture; } private static void Buttons() { EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Open")) OpenPrefab(); if (GUILayout.Button("Save")) Save(); if (GUILayout.Button("Reset")) { GameData.ClearAll(); Load(); } EditorGUILayout.EndHorizontal(); } private static void OpenPrefab() { string levelName = LevelSettings.GetPrefabPath(_custom.progress.sequence[(int)_custom.progress.completed]); AssetDatabase.OpenAsset(AssetDatabase.LoadAssetAtPath($"Assets/Resources/{levelName}.prefab")); } private static void Save() { Error.Assert(EditorApplication.isPlaying == false, "Removed state files might be rewritten by running game"); PersistError error = _save.DevWriteToFile(GameData.DefaultDataFile, _custom); Log.Debug($"CheatsWindow.Save: {error.Code}"); _save.TryLoadOrCreateNew(); _original = _save.DevGetState(); _custom = (DataGame)_original.clone(); } private static void TabOfHotkeys() { EditorGUILayout.BeginHorizontal(); EditorGUILayout.HelpBox( "Toggle UI visibility: (SPACE)\n" + "", MessageType.Info); EditorGUILayout.EndHorizontal(); } }