using System.Collections.Generic; using Godot; using Godot.Collections; using Newtonsoft.Json; public partial class SaveFile { public enum Letters { None = -1, MoAd, KanakoDay2, VirgilDay2, CrumpledNoteD2, NoiseComplaint } public enum Flags { NULL = 99999, HasNecklace = -10, PartySplit = -9, FullStorage = -8, FullWeapon = -7, FullArmor = -6, FullLInv = -5, FullDInv = -4, SpareMore = -3, FightMore = -2, None = -1, IsInDW = 0, KanakoFollowing = 1, AxisFollowing = 2, StephFollowing = 3, JuneFollowing = 4, SawKetsukaneWindow = 5, AxisCutoutKanako = 6, Day1End = 7, Day2End = 8, Day3End = 9, Day4End = 10, Day5End = 11, Day6End = 12, CerobaDay1Talk = 13, IntroEvent = 14, WeirdStart = 15, FirstCrateGate = 16, FirstPuzzleSign = 17, FirstDW1Chest = 18, SavedKanakoCh1 = 19, ApprehendTutorial = 20, KanakoFirstDWTalk = 21, KanakoRoomAfterRescueTalk = 22, SecondDW1Chest = 23, EnemyAfterKanako1 = 24, EnemyAfterKanako2 = 25, EnemyAfterKanako3 = 26, FreedFromJail = 27, MossChecked = 28, AteMoss = 29, KanakoCommentsOnMoss = 30, PrisonTriedCrack = 31, DisagreedWardenFirstTalk = 32, WardenExposited = 33, KanakoBearTalk = 34, DarkPrisonRightTalk = 35, DarkPrisonSouthTalk = 36, BearingDefeated = 37, WeaponTalk = 38, KanakoTalkAfterTutorial = 39, DidApprehendTutorial = 40, KanakoLakeTalk = 41, MoneyChestLake = 42, PenniltonFought = 43, PenniltonCaught = 44, LuncherFought = 45, LuncherCaught = 46, BearingFought = 47, BearingCaught = 48, BackpackFirstTalk = 49, RubbermanTalk = 50, KanakoTownDiag = 51, KanakoPhoneEvent = 52, ChestBridgeRoom = 53, KanakoLandscapeDiag = 54, PencellerSidePath = 55, EraserSidePath = 56, PencellerSidePath2 = 57, ChestBridgeRoom2 = 58, WardenApprehendRegular = 59, PeniltonDEAD = 60, LuncherDEAD = 61, BearingDEAD = 62, KanakoMemoryGameRoomBefore = 63, KanakoMemoryGameInProgress = 64, KanakoMemoryGameRoomAfter = 65, KanakoPostPennyWeird = 66, KanakoPostPennyNormal = 67, MP3DarknerTalk = 68, BeatMemoryGame = 69, YellowPaintEvent = 70, MemoryGameWin = 71, PenGuyFirstTalk = 72, KanakoLakeWeird = 73, BearingFortFirstPuzzle = 74, KanakoTalkBFortFirstPRoom = 75, BFortTrashCan = 76, KanakoGateNote = 77, KanakoGateEvent = 78, BearingFortMainGate = 79, BearingFortUpRoomLock = 80, MopperMainHall1 = 81, MopperMainHall2 = 82, PencellerMainHall = 83, WeirdedOnce = 84, BearFortLeftMinigame = 85, BBallTalk1 = 86, BBallTalk2 = 87, BBallPlayedOnce = 88, BBallKanakoTalk1 = 89, BBallKanakoTalk2 = 90, BBallKanakoTalk3 = 91, KanakoWeirdTalkBreakRoom = 92, KanakoTalkBreakRoom = 93, MopperBigCorridor1 = 94, MopperBigCorridor2 = 95, MopperBigCorridor3 = 96, MopperBigCorridor4 = 97, KanakoTalkFortBigCorridor = 98, KanakoWarningBeforeBear = 99, KanakoTalkBearPrison = 100, KanakoWarningBeforeFountain = 101, BearFortTreasureRoom = 102, BearFortGotTreasure = 103, BearFortTreasureTalk = 104, BearTreasureChest1 = 105, BearTreasureChest2 = 106, BearTreasureChest3 = 107, BearFortTreasureInvFull = 108, BearTreasureLost = 109, KanakoTalkTreasurePost = 110, NightTime = 111, SchoolFountainSealed = 112, FoxFirstTalk = 113, FoxDefeated = 114, FoxFullInvSpare = 115, FoxFullInvDefeat = 116, FoxGotItem = 117, PenGuyReturn = 118, SchoolCheckedLock = 119, MagicDoorActive = 120, WardenTalkEndDay1 = 121, WardenInnocentTalk = 122, DinaDay1Talk = 123, VirgilDay1 = 124, AfterDinnerDay1 = 125, MartletHouseCheckD1 = 126, IgnoredCerobaCallD1 = 127, FirstKetsuShopEvent = 128, CerobaTalkChujinDoor = 129, KanakoDiscussDay1 = 130, ListenedToCCDay1 = 131, ReturnedNecklace = 132, GaveLetterMartlet = 133, LuncherDisappear = 134, StarloDay1 = 135, VirgilDay1Weird = 136, VirgilDay1Rejected = 137, NicePenceller = 138, BearingSpareItem = 139, BearingSpared = 140, KanakoTalkPostBearingF = 141, PenGuyPrison = 142, KanakoTalkNorthPrisonTalk = 143, KanakoApprehendTalk = 144, MoochTalkD1 = 145, AnnoyedDecibat = 146, MartEventDay2 = 147, MailWhaleDay2 = 148, KanakoEventDay2 = 149, SchoolRecessDay2 = 150, JuneRecessDay2 = 151, MelodyEventDay2 = 152, RedLetterDay2 = 153, EnterDarkJailDay2 = 154, WardenTalkDay2 = 155, PostWardenOutDWTalkDay2 = 156, CerobaEventDay2 = 157, FridgeDay2 = 158, Day2KanakoRoomCheck = 159, KanakoRedLetterDWEntTalk = 160, AxisEvent = 161, AxisFirstTalk = 162, AxisTalkSlide = 163, DW2Overview = 164, DW2MagicDoor = 165, LockLightWorldPortal = 166, WardenRobotopiaTalk = 167, Gizzard1 = 168, Gizzard2 = 169, ChestDW2_1 = 170, FirstPuzzleDW2 = 171, Gizzard3 = 172, KanakoTalkWaterGun = 173, Puzzle2_DW2 = 174, ChestDW2_2 = 175, DW2Room2Stapler = 176, DW2Room2Wrench = 177, DW2Room2Gear = 178, DW2PlanTalk = 179, DW2TownTVEvent = 180, Puzzle3_DW2 = 181, FactoryMainEnemyLeft = 182, FactoryMainEnemyRight = 183, FactoryPuzzle1 = 184, FactoryPuzzle2 = 185, AxisPuzzleTalk = 186, EnemyBeforeFactory = 187, FactoryRightPuzzle1 = 188, TalkFactoryRight = 189, ChestFactoryRight = 190, FactoryRightEnemy = 191, ChestFactoryLeft = 192, ChestFactoryLeft2 = 193, TalkFactoryLeft = 194, FactoryLeftEnemy1 = 195, FactoryLeftEnemy2 = 196, FactoryFirstSwitch = 197, ClawTalk = 198, TramEvent = 199, AxisTrashEvent = 200, AxisSoloTalk = 201, AxisTrashTreasure = 202, PuzzleChujinDWTrash = 203, AxisTrashPuzzleTalk = 204, AxisHandGet = 205, FirstUpstairsTalk = 206, UpstairsOverview = 207, BunBunEvent1 = 208, BunBunEvent2 = 209, KanakoFountainTalk = 210, KanakoTosterTalk = 211, UpstairsGreenChest = 212, UpstairsTalk2 = 213, RangerEvent = 214, RangerTalk = 215, RangerBlueBalloon = 216, ArchiveChestOutside = 217, ArchivesPC = 218, PenGuyTalkDay2 = 219, ChujinShopTalk = 220, PenGuyRestRoom = 221, SchoolJokeDuoD2 = 222, BBallPity1 = 223, BBallPity2 = 224, BBallPitied = 225, BellCrusherPity = 226, BBallChestOpen = 227, EnemyAfterKanako4 = 228, EnemyAfterKanako5 = 229, EnemyAfterKanako6 = 230, AfterKanakoBridgeOpen = 231, PedlaHospitalD1 = 232, KTalkPrisonRightBD = 233, WarpDoorFirst = 234, BenchTSouth = 235, BenchTMain = 236, BenchDW2Archive = 237, KanakoFishFirstTalk = 238, FishGuyFirstTalk = 239, FishGuyTaskDay2 = 240, PedlaHospitalD2 = 241, StarloDadDay2 = 242, ViolettaD2 = 243, BlackjackD2 = 244, MochaEventD1 = 245, StarloEventD2 = 246, RobaDay2Early = 247 } public static SaveFile current; public HashSet flags = new HashSet(); public int[] values = new int[100]; public int[] time = new int[3]; public List partyData = new List(); public List lwItems = new List(); public List dwItems = new List(); public List dwArmor = new List(); public List dwWeapon = new List(); public List storage = new List(); public List dwKey = new List(); public List activeParty = new List(); public List letters = new List(); public HashSet readLetters = new HashSet(); public List apprehended = new List(); public System.Collections.Generic.Dictionary fishes = new System.Collections.Generic.Dictionary(); public List followers = new List(); public bool easyMode; public int gold = 3; public int dollars; public int love = 1; public int lv = 1; public int exp; public int slot; public Vector2 position; public Room.IDs room; public string roomName; public const int maxInvDW = 12; public const int maxEquip = 48; public static bool HasFlags(Array flags) { if (flags == null || flags.Count == 0) { return true; } for (int i = 0; i < flags.Count; i++) { if (!HasFlag(flags[i])) { return false; } } return true; } public static string GetRoomName(Room.IDs id = Room.IDs.None) { if (id == Room.IDs.None) { id = Room.current.id; } if (Texts.roomNames.TryGetValue(id, out var value)) { return value; } return "??????"; } public static bool HasFlag(Flags flags) { return flags switch { Flags.HasNecklace => current.lwItems.Contains(Items.IDs.KetsukaneHeirloom), Flags.PartySplit => Player.instance.splitEntity != null, Flags.SpareMore => current.values[1] >= current.values[2], Flags.FightMore => current.values[1] < current.values[2], Flags.FullStorage => Items.CheckFull(Items.Type.Storage), Flags.FullWeapon => Items.CheckFull(Items.Type.Weapon), Flags.FullArmor => Items.CheckFull(Items.Type.Equip), Flags.FullLInv => Items.CheckFull(Items.Type.LightWorld), Flags.FullDInv => Items.CheckFull(Items.Type.Normal), _ => current.flags.Contains(flags), }; } public static void AddMoney(int value) { current.dollars = Mathf.Clamp(current.dollars + value, 0, 9999); } public static bool AddFlag(Flags flag) { if (flag != Flags.None && !current.flags.Contains(flag)) { current.flags.Add(flag); return true; } return false; } public static bool CanDo(Array spawn, Array despawn) { spawn?.Remove(Flags.None); despawn?.Remove(Flags.None); if (spawn == null || spawn.Count == 0 || HasFlags(spawn)) { if (despawn == null || despawn.Count == 0) { return true; } return !HasFlags(despawn); } return false; } public static bool Save() { current.roomName = Room.current.mapName; current.position = Player.instance.GlobalPosition; current.room = Room.current.id; current.partyData = Party.GetPartyStats(); current.lv = Party.party[0].LV; try { using FileAccess fileAccess = FileAccess.Open("user://Save" + current.slot + ".dat", FileAccess.ModeFlags.Write); fileAccess.StoreString(JsonConvert.SerializeObject(current)); fileAccess.Close(); } catch { return false; } return true; } public void LoadStats() { for (int i = 0; i < Party.party.Count; i++) { Party.party[i].HP = partyData[i][0]; Party.party[i].MAXHP = partyData[i][1]; Party.party[i].ATKBONUS = partyData[i][2]; Party.party[i].DEFBONUS = partyData[i][3]; Party.party[i].LV = partyData[i][4]; Party.party[i].EQUIP = new int[3] { partyData[i][5], partyData[i][6], partyData[i][7] }; if (partyData[i].Length > 8) { Party.party[i].title = partyData[i][8]; } if (partyData[i].Length > 9) { Party.party[i].HPBONUS = partyData[i][9]; } } } }