diff --git a/BossChecklist.cs b/BossChecklist.cs index 292569e..bb973e3 100644 --- a/BossChecklist.cs +++ b/BossChecklist.cs @@ -1,10 +1,12 @@ using BossChecklist.Systems; +using Microsoft.Xna.Framework; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using Terraria; +using Terraria.Chat; using Terraria.ID; using Terraria.Localization; using Terraria.ModLoader; @@ -446,6 +448,52 @@ public override void HandlePacket(BinaryReader reader, int whoAmI) { recordIndex = reader.ReadInt32(); Main.LocalPlayer.GetModPlayer().RecordsForWorld?[recordIndex].StartTracking(); break; + case PacketMessageType.RequestBossStateToggle: + if (Main.netMode == NetmodeID.Server) { + string bossKey1 = reader.ReadString(); + bool downed1 = reader.ReadBoolean(); + EntryInfo entry = BossChecklist.bossTracker.FindEntryFromKey(bossKey1); + + if (!Networking.TryApplyBossStateToggle(bossKey1, downed1)) { + ChatHelper.BroadcastChatMessage( + instance.GetLocalization("Configs.DebugTools.Failed").ToNetworkText(entry.name), + Color.Red + ); + break; + } + + NetMessage.SendData(MessageID.WorldData); + + // show text to let other player know which boss's defeat state toggled + ChatHelper.BroadcastChatMessage( + instance.GetLocalization("Configs.DebugTools.Successed") + .ToNetworkText( + entry.name, + downed1 + ? instance.GetLocalization("Configs.DebugTools.Defeated") + : instance.GetLocalization("Configs.DebugTools.Alive") + ), + Color.LightGreen + ); + + // in case some mod's data can not be sent + ModPacket packet1 = GetPacket(); + packet1.Write((byte)PacketMessageType.SyncBossState); + packet1.Write(bossKey1); + packet1.Write(downed1); + packet1.Send(); // Server --> All Clients + } + break; + + case PacketMessageType.SyncBossState: + if (Main.netMode == NetmodeID.MultiplayerClient) { + string bossKey2 = reader.ReadString(); + bool downed2 = reader.ReadBoolean(); + + if (Networking.TryApplyBossStateToggle(bossKey2, downed2)) + BossLogSystem.Instance?.BossLog?.RefreshPageContent(); + } + break; default: Logger.Error($"Unknown Message type: {msgType}"); break; diff --git a/BossTracker.cs b/BossTracker.cs index 34caee0..fe77a78 100644 --- a/BossTracker.cs +++ b/BossTracker.cs @@ -117,102 +117,145 @@ public BossTracker() { private void InitializeVanillaEntries() { SortedEntries = new List { // Bosses -- Vanilla - EntryInfo.MakeVanillaBoss(EntryType.Boss, KingSlime, "NPCName.KingSlime", NPCID.KingSlime, () => NPC.downedSlimeKing) + EntryInfo.MakeVanillaBoss(EntryType.Boss, KingSlime, "NPCName.KingSlime", NPCID.KingSlime, () => NPC.downedSlimeKing, (@new) => { NPC.downedSlimeKing = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.KingSlime}"), - EntryInfo.MakeVanillaBoss(EntryType.Boss, EyeOfCthulhu, "NPCName.EyeofCthulhu", NPCID.EyeofCthulhu, () => NPC.downedBoss1), - EntryInfo.MakeVanillaBoss(EntryType.Boss, EaterOfWorlds, "NPCName.EaterofWorldsHead", new List() { NPCID.EaterofWorldsHead, NPCID.EaterofWorldsBody, NPCID.EaterofWorldsTail }, () => NPC.downedBoss2) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, EyeOfCthulhu, "NPCName.EyeofCthulhu", NPCID.EyeofCthulhu, () => NPC.downedBoss1, (@new) => { NPC.downedBoss1 = @new; }), + + EntryInfo.MakeVanillaBoss(EntryType.Boss, EaterOfWorlds, "NPCName.EaterofWorldsHead", new List() { NPCID.EaterofWorldsHead, NPCID.EaterofWorldsBody, NPCID.EaterofWorldsTail }, () => NPC.downedBoss2, (@new) => { NPC.downedBoss2 = @new; }) .WithCustomAvailability(() => !WorldGen.crimson || Main.drunkWorld) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.EaterofWorldsHead}"), - EntryInfo.MakeVanillaBoss(EntryType.Boss, EaterOfWorlds, "NPCName.BrainofCthulhu", NPCID.BrainofCthulhu, () => NPC.downedBoss2) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, EaterOfWorlds, "NPCName.BrainofCthulhu", NPCID.BrainofCthulhu, () => NPC.downedBoss2, (@new) => { NPC.downedBoss2 = @new; }) .WithCustomAvailability(() => WorldGen.crimson || Main.drunkWorld), - EntryInfo.MakeVanillaBoss(EntryType.Boss, QueenBee, "NPCName.QueenBee", NPCID.QueenBee, () => NPC.downedQueenBee), - EntryInfo.MakeVanillaBoss(EntryType.Boss, Skeletron, "NPCName.SkeletronHead", new List() { NPCID.SkeletronHead }, () => NPC.downedBoss3) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, QueenBee, "NPCName.QueenBee", NPCID.QueenBee, () => NPC.downedQueenBee, (@new) => { NPC.downedQueenBee = @new; }), + + EntryInfo.MakeVanillaBoss(EntryType.Boss, Skeletron, "NPCName.SkeletronHead", new List() { NPCID.SkeletronHead }, () => NPC.downedBoss3, (@new) => { NPC.downedBoss3 = @new; }) .WithCustomLimbs(new List() { NPCID.SkeletronHand }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.SkeletronHead}"), - EntryInfo.MakeVanillaBoss(EntryType.Boss, DeerClops, "NPCName.Deerclops", NPCID.Deerclops, () => NPC.downedDeerclops) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, DeerClops, "NPCName.Deerclops", NPCID.Deerclops, () => NPC.downedDeerclops, (@new) => { NPC.downedDeerclops = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.Deerclops}"), - EntryInfo.MakeVanillaBoss(EntryType.Boss, WallOfFlesh, "NPCName.WallofFlesh", new List() { NPCID.WallofFlesh }, () => Main.hardMode) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, WallOfFlesh, "NPCName.WallofFlesh", new List() { NPCID.WallofFlesh }, () => Main.hardMode, (@new) => { Main.hardMode = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.WallofFlesh}"), - EntryInfo.MakeVanillaBoss(EntryType.Boss, QueenSlime, "NPCName.QueenSlimeBoss", NPCID.QueenSlimeBoss, () => NPC.downedQueenSlime) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, QueenSlime, "NPCName.QueenSlimeBoss", NPCID.QueenSlimeBoss, () => NPC.downedQueenSlime, (@new) => { NPC.downedQueenSlime = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.QueenSlimeBoss}"), - EntryInfo.MakeVanillaBoss(EntryType.Boss, TheTwins, "Enemies.TheTwins", new List() { NPCID.Retinazer, NPCID.Spazmatism }, () => NPC.downedMechBoss2) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, TheTwins, "Enemies.TheTwins", new List() { NPCID.Retinazer, NPCID.Spazmatism }, () => NPC.downedMechBoss2, (@new) => { NPC.downedMechBoss2 = @new; }) .WithCustomLimbs(new List() { NPCID.Retinazer, NPCID.Spazmatism }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.Retinazer}"), - EntryInfo.MakeVanillaBoss(EntryType.Boss, TheDestroyer, "NPCName.TheDestroyer", NPCID.TheDestroyer, () => NPC.downedMechBoss1) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, TheDestroyer, "NPCName.TheDestroyer", NPCID.TheDestroyer, () => NPC.downedMechBoss1, (@new) => { NPC.downedMechBoss1 = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.TheDestroyer}"), - EntryInfo.MakeVanillaBoss(EntryType.Boss, SkeletronPrime, "NPCName.SkeletronPrime", NPCID.SkeletronPrime, () => NPC.downedMechBoss3) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, SkeletronPrime, "NPCName.SkeletronPrime", NPCID.SkeletronPrime, () => NPC.downedMechBoss3, (@new) => { NPC.downedMechBoss3 = @new; }) .WithCustomLimbs(new List() { NPCID.PrimeCannon, NPCID.PrimeSaw, NPCID.PrimeVice, NPCID.PrimeLaser }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.SkeletronPrime}"), - EntryInfo.MakeVanillaBoss(EntryType.Boss, Plantera, "NPCName.Plantera", NPCID.Plantera, () => NPC.downedPlantBoss), - EntryInfo.MakeVanillaBoss(EntryType.Boss, Golem, "NPCName.Golem", new List() { NPCID.Golem }, () => NPC.downedGolemBoss) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, Plantera, "NPCName.Plantera", NPCID.Plantera, () => NPC.downedPlantBoss, (@new) => { NPC.downedPlantBoss = @new; }), + + EntryInfo.MakeVanillaBoss(EntryType.Boss, Golem, "NPCName.Golem", new List() { NPCID.Golem }, () => NPC.downedGolemBoss, (@new) => { NPC.downedGolemBoss = @new; }) .WithCustomLimbs(new List() { NPCID.GolemFistLeft, NPCID.GolemFistRight, NPCID.GolemHead }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.Golem}") .WithCustomHeadIcon($"Terraria/Images/NPC_Head_Boss_5"), - EntryInfo.MakeVanillaBoss(EntryType.Boss, Betsy, "NPCName.DD2Betsy", NPCID.DD2Betsy, () => DD2Event.DownedInvasionT3) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, Betsy, "NPCName.DD2Betsy", NPCID.DD2Betsy, () => DD2Event.DownedInvasionT3, (@new) => { DD2Event.DownedInvasionT3 = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.DD2Betsy}"), // No despawn message due to being in an event - EntryInfo.MakeVanillaBoss(EntryType.Boss, EmpressOfLight, "NPCName.HallowBoss", NPCID.HallowBoss, () => NPC.downedEmpressOfLight) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, EmpressOfLight, "NPCName.HallowBoss", NPCID.HallowBoss, () => NPC.downedEmpressOfLight, (@new) => { NPC.downedEmpressOfLight = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.HallowBoss}"), - EntryInfo.MakeVanillaBoss(EntryType.Boss, DukeFishron, "NPCName.DukeFishron", NPCID.DukeFishron, () => NPC.downedFishron), - EntryInfo.MakeVanillaBoss(EntryType.Boss, LunaticCultist, "NPCName.CultistBoss", NPCID.CultistBoss, () => NPC.downedAncientCultist) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, DukeFishron, "NPCName.DukeFishron", NPCID.DukeFishron, () => NPC.downedFishron, (@new) => { NPC.downedFishron = @new; }), + + EntryInfo.MakeVanillaBoss(EntryType.Boss, LunaticCultist, "NPCName.CultistBoss", NPCID.CultistBoss, () => NPC.downedAncientCultist, (@new) => { NPC.downedAncientCultist = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.CultistBoss}"), - EntryInfo.MakeVanillaBoss(EntryType.Boss, Moonlord, "Enemies.MoonLord", new List() { NPCID.MoonLordHead, NPCID.MoonLordCore }, () => NPC.downedMoonlord) + + EntryInfo.MakeVanillaBoss(EntryType.Boss, Moonlord, "Enemies.MoonLord", new List() { NPCID.MoonLordHead, NPCID.MoonLordCore }, () => NPC.downedMoonlord, (@new) => { NPC.downedMoonlord = @new; }) .WithCustomLimbs(new List() { NPCID.MoonLordHead, NPCID.MoonLordHand }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.MoonLordHead}"), // Minibosses and Events -- Vanilla - EntryInfo.MakeVanillaEvent(TorchGod, "NPCName.TorchGod", () => Main.LocalPlayer.unlockedBiomeTorches) + EntryInfo.MakeVanillaEvent(TorchGod, "NPCName.TorchGod", () => Main.LocalPlayer.unlockedBiomeTorches,(@new) => + { + foreach (Player p in Main.player) + p.unlockedBiomeTorches = @new; + }) .WithCustomHeadIcon($"Terraria/Images/Item_{ItemID.TorchGodsFavor}"), - EntryInfo.MakeVanillaEvent(BloodMoon, "Bestiary_Events.BloodMoon", () => Systems.DownedSystem.downedBloodMoon) + + EntryInfo.MakeVanillaEvent(BloodMoon, "Bestiary_Events.BloodMoon", () => DownedSystem.downedBloodMoon, (@new) => { DownedSystem.downedBloodMoon = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/EventBloodMoon") .WithCustomHeadIcon($"BossChecklist/Resources/BossTextures/EventBloodMoon_Head"), - // EntryInfo.MakeVanillaBoss(BossChecklistType.MiniBoss,WallOfFlesh + 0.1f, "Clown", new List() { NPCID.Clown}, () => NPC.downedClown, new List() { }, $"Spawns during Hardmode Bloodmoon"), - EntryInfo.MakeVanillaEvent(GoblinArmy, "Goblin Army", () => NPC.downedGoblins) + + // EntryInfo.MakeVanillaBoss(BossChecklistType.MiniBoss,WallOfFlesh + 0.1f, "Clown", new List() { NPCID.Clown}, () => NPC.downedClown,(@new) => {NPC.downedClown = @new;} new List() { }, $"Spawns during Hardmode Bloodmoon"), + + EntryInfo.MakeVanillaEvent(GoblinArmy, "Goblin Army", () => NPC.downedGoblins,(@new) => {NPC.downedGoblins = @new; }) .WithCustomTranslationKey("LegacyInterface.88") .WithCustomPortrait($"BossChecklist/Resources/BossTextures/EventGoblinArmy") .WithCustomHeadIcon("Terraria/Images/Extra_9"), - EntryInfo.MakeVanillaEvent(OldOnesArmy, "Old One's Army", () => DD2Event.DownedInvasionAnyDifficulty) + + // TODO:Split this into three event + EntryInfo.MakeVanillaEvent(OldOnesArmy, "Old One's Army", () => DD2Event.DownedInvasionAnyDifficulty,null) .WithCustomTranslationKey("DungeonDefenders2.InvasionProgressTitle") .WithCustomPortrait($"BossChecklist/Resources/BossTextures/EventOldOnesArmy") .WithCustomHeadIcon("Terraria/Images/Extra_79"), - EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, DarkMage, "NPCName.DD2DarkMageT3", new List() { NPCID.DD2DarkMageT3, NPCID.DD2DarkMageT1 }, () => Systems.DownedSystem.downedDarkMage) + + EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, DarkMage, "NPCName.DD2DarkMageT3", new List() { NPCID.DD2DarkMageT3, NPCID.DD2DarkMageT1 }, () => DownedSystem.downedDarkMage,(@new) => { DownedSystem.downedDarkMage = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.DD2DarkMageT3}"), - EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, Ogre, "NPCName.DD2OgreT3", new List() { NPCID.DD2OgreT3, NPCID.DD2OgreT2 }, () => Systems.DownedSystem.downedOgre) + + EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, Ogre, "NPCName.DD2OgreT3", new List() { NPCID.DD2OgreT3, NPCID.DD2OgreT2 }, () => DownedSystem.downedOgre, (@new) => { DownedSystem.downedOgre = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.DD2OgreT3}"), - EntryInfo.MakeVanillaEvent(FrostLegion, "Frost Legion", () => NPC.downedFrost) + + EntryInfo.MakeVanillaEvent(FrostLegion, "Frost Legion", () => NPC.downedFrost,(@new) => { NPC.downedFrost = @new; }) .WithCustomTranslationKey("LegacyInterface.87") .WithCustomAvailability(() => Main.xMas) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/EventFrostLegion") .WithCustomHeadIcon("Terraria/Images/Extra_7"), - EntryInfo.MakeVanillaEvent(PirateInvasion, "Pirate Invasion", () => NPC.downedPirates) + + EntryInfo.MakeVanillaEvent(PirateInvasion, "Pirate Invasion", () => NPC.downedPirates, (@new) => { NPC.downedPirates = @new; }) .WithCustomTranslationKey("LegacyInterface.86") .WithCustomPortrait($"BossChecklist/Resources/BossTextures/EventPirateInvasion") .WithCustomHeadIcon("Terraria/Images/Extra_11"), - EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, PirateShip, "NPCName.PirateShip", new List() { NPCID.PirateShip }, () => Systems.DownedSystem.downedFlyingDutchman) + + EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, PirateShip, "NPCName.PirateShip", new List() { NPCID.PirateShip }, () => DownedSystem.downedFlyingDutchman, (@new) => { DownedSystem.downedFlyingDutchman = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.PirateShip}"), - EntryInfo.MakeVanillaEvent(SolarEclipse, "Bestiary_Events.Eclipse", () => Systems.DownedSystem.downedSolarEclipse) + + EntryInfo.MakeVanillaEvent(SolarEclipse, "Bestiary_Events.Eclipse", () => DownedSystem.downedSolarEclipse, (@new) => { DownedSystem.downedSolarEclipse = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/EventSolarEclipse") .WithCustomHeadIcon($"BossChecklist/Resources/BossTextures/EventSolarEclipse_Head"), - EntryInfo.MakeVanillaEvent(PumpkinMoon, "Pumpkin Moon", () => Systems.DownedSystem.downedPumpkinMoon) + + EntryInfo.MakeVanillaEvent(PumpkinMoon, "Pumpkin Moon", () => DownedSystem.downedPumpkinMoon, (@new) => { DownedSystem.downedPumpkinMoon = @new; }) .WithCustomTranslationKey("LegacyInterface.84") .WithCustomPortrait($"BossChecklist/Resources/BossTextures/EventPumpkinMoon") .WithCustomHeadIcon($"Terraria/Images/Extra_12"), - EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, MourningWood, "NPCName.MourningWood", new List() { NPCID.MourningWood }, () => NPC.downedHalloweenTree), - EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, Pumpking, "NPCName.Pumpking", new List() { NPCID.Pumpking }, () => NPC.downedHalloweenKing) + + EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, MourningWood, "NPCName.MourningWood", new List() { NPCID.MourningWood }, () => NPC.downedHalloweenTree, (@new) => { NPC.downedHalloweenTree = @new; }), + + EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, Pumpking, "NPCName.Pumpking", new List() { NPCID.Pumpking }, () => NPC.downedHalloweenKing, (@new) => { NPC.downedHalloweenKing = @new; }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/Boss{NPCID.Pumpking}"), - EntryInfo.MakeVanillaEvent(FrostMoon, "Frost Moon", () => Systems.DownedSystem.downedFrostMoon) + + EntryInfo.MakeVanillaEvent(FrostMoon, "Frost Moon", () => DownedSystem.downedFrostMoon, (@new) => { DownedSystem.downedFrostMoon = @new; }) .WithCustomTranslationKey("LegacyInterface.83") .WithCustomPortrait($"BossChecklist/Resources/BossTextures/EventFrostMoon") .WithCustomHeadIcon($"Terraria/Images/Extra_8"), - EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, Everscream, "NPCName.Everscream", new List() { NPCID.Everscream }, () => NPC.downedChristmasTree), - EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, SantaNK1, "NPCName.SantaNK1", new List() { NPCID.SantaNK1 }, () => NPC.downedChristmasSantank), - EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, IceQueen, "NPCName.IceQueen", new List() { NPCID.IceQueen }, () => NPC.downedChristmasIceQueen), - EntryInfo.MakeVanillaEvent(MartianMadness, "Martian Madness", () => NPC.downedMartians) + + EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, Everscream, "NPCName.Everscream", new List() { NPCID.Everscream }, () => NPC.downedChristmasTree, (@new) => { NPC.downedChristmasTree = @new; }), + + EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, SantaNK1, "NPCName.SantaNK1", new List() { NPCID.SantaNK1 }, () => NPC.downedChristmasSantank, (@new) => { NPC.downedChristmasSantank = @new; }), + + EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, IceQueen, "NPCName.IceQueen", new List() { NPCID.IceQueen }, () => NPC.downedChristmasIceQueen, (@new) => { NPC.downedChristmasIceQueen = @new; }), + + EntryInfo.MakeVanillaEvent(MartianMadness, "Martian Madness", () => NPC.downedMartians, (@new) => { NPC.downedMartians = @new; }) .WithCustomTranslationKey("LegacyInterface.85") .WithCustomPortrait($"BossChecklist/Resources/BossTextures/EventMartianMadness") .WithCustomHeadIcon($"Terraria/Images/Extra_10"), - EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, MartianSaucer, "NPCName.MartianSaucer", new List() { NPCID.MartianSaucer, NPCID.MartianSaucerCore }, () => Systems.DownedSystem.downedMartianSaucer), - EntryInfo.MakeVanillaEvent(LunarEvent, "Lunar Event", () => NPC.downedTowers) + + EntryInfo.MakeVanillaBoss(EntryType.MiniBoss, MartianSaucer, "NPCName.MartianSaucer", new List() { NPCID.MartianSaucer, NPCID.MartianSaucerCore }, () => DownedSystem.downedMartianSaucer, (@new) => { DownedSystem.downedMartianSaucer = @new; }), + + EntryInfo.MakeVanillaEvent(LunarEvent, "Lunar Event", () => NPC.downedTowers,(@new) => { NPC.downedTowerSolar = @new; NPC.downedTowerNebula = @new;NPC.downedTowerVortex = @new; NPC.downedTowerStardust = @new; }) .WithCustomTranslationKey("Mods.BossChecklist.Checklist.CelestialPillars") .WithCustomLimbs(new List() { NPCID.LunarTowerVortex, NPCID.LunarTowerStardust, NPCID.LunarTowerNebula, NPCID.LunarTowerSolar }) .WithCustomPortrait($"BossChecklist/Resources/BossTextures/EventLunarEvent") diff --git a/Configs.cs b/Configs.cs index 9649227..6839ae4 100644 --- a/Configs.cs +++ b/Configs.cs @@ -35,7 +35,8 @@ public class BossLogConfiguration : ModConfig { [Expand(false)] [BackgroundColor(100, 70, 60)] public DebugTools Debug { get; set; } = new DebugTools(); - public class DebugTools { + public class DebugTools + { [BackgroundColor(250, 235, 215)] [DefaultValue(false)] public bool ModCallLogVerbose { get; set; } @@ -56,6 +57,10 @@ public class DebugTools { [DefaultValue(false)] public bool ShowCollectionType { get; set; } + [BackgroundColor(250, 235, 215)] + [DefaultValue(false)] + public bool EnableBossStateToggle { get; set; } + [BackgroundColor(250, 235, 215)] [DefaultValue(false)] public bool EnabledResetOptions { get; set; } diff --git a/EntryInfo.cs b/EntryInfo.cs index 8784488..a39a713 100644 --- a/EntryInfo.cs +++ b/EntryInfo.cs @@ -42,6 +42,7 @@ internal class EntryInfo { internal Dictionary npcLimbs; internal float progression; internal Func downed; + internal Action setDowned; internal Func available; internal bool hidden; internal Func customDespawnMessages; @@ -330,6 +331,14 @@ internal EntryInfo(EntryType entryType, string modSource, string internalName, o if (icons.Count > 0) headIconTextures = () => icons; } + + if (extraData?.ContainsKey("setDowned") == true) { + // toggle whether boss is defeated + object setDowned = extraData["setDowned"]; + if (setDowned is Action) { + this.setDowned = setDowned as Action; + } + } } // Workaround for vanilla events with illogical translation keys. @@ -381,7 +390,7 @@ internal EntryInfo WithCustomHeadIcon(List texturePaths) { return this; } - internal static EntryInfo MakeVanillaBoss(EntryType type, float val, string key, int npcID, Func downed) { + internal static EntryInfo MakeVanillaBoss(EntryType type, float val, string key, int npcID, Func downed, Action setDowned) { string nameKey = key.Substring(key.LastIndexOf(".") + 1); // BossChecklist only has despawn messages for vanilla Bosses @@ -422,11 +431,12 @@ internal static EntryInfo MakeVanillaBoss(EntryType type, float val, string key, { "spawnItems", BossTracker.EntrySpawnItems.GetValueOrDefault($"Terraria {nameKey}") }, { "collectibles", BossTracker.EntryCollectibles.GetValueOrDefault($"Terraria {nameKey}") }, { "despawnMessage", customMessages }, + { "setDowned", setDowned }, } ); } - internal static EntryInfo MakeVanillaBoss(EntryType type, float val, string key, List ids, Func downed) { + internal static EntryInfo MakeVanillaBoss(EntryType type, float val, string key, List ids, Func downed, Action setDowned) { string nameKey = key.Substring(key.LastIndexOf(".") + 1).Replace(" ", "").Replace("'", ""); if (nameKey.EndsWith("Head")) nameKey = nameKey.Substring(0, nameKey.Length - 4); @@ -467,11 +477,12 @@ internal static EntryInfo MakeVanillaBoss(EntryType type, float val, string key, { "spawnItems", BossTracker.EntrySpawnItems.GetValueOrDefault($"Terraria {nameKey}") }, { "collectibles", BossTracker.EntryCollectibles.GetValueOrDefault($"Terraria {nameKey}") }, { "despawnMessage", customMessages }, + { "setDowned", setDowned }, } ); } - internal static EntryInfo MakeVanillaEvent(float val, string key, Func downed) { + internal static EntryInfo MakeVanillaEvent(float val, string key, Func downed, Action setDowned) { string nameKey = key.Substring(key.LastIndexOf(".") + 1).Replace(" ", "").Replace("'", ""); return new EntryInfo( entryType: EntryType.Event, @@ -486,6 +497,7 @@ internal static EntryInfo MakeVanillaEvent(float val, string key, Func dow { "spawnInfo", BossChecklist.instance.GetLocalization($"BossSpawnInfo.{nameKey}") }, { "spawnItems", BossTracker.EntrySpawnItems.GetValueOrDefault($"Terraria {nameKey}") }, { "collectibles", BossTracker.EntryCollectibles.GetValueOrDefault($"Terraria {nameKey}") }, + { "setDowned", setDowned }, } ); } diff --git a/Localization/TranslationsNeeded.txt b/Localization/TranslationsNeeded.txt index eccb034..36cea07 100644 --- a/Localization/TranslationsNeeded.txt +++ b/Localization/TranslationsNeeded.txt @@ -1,9 +1,9 @@ -en-US, 336/336, 100%, missing 0 -de-DE, 319/336, 95%, missing 17 -it-IT, 3/336, 1%, missing 333 -fr-FR, 316/336, 94%, missing 20 -es-ES, 79/336, 24%, missing 257 -ru-RU, 317/336, 94%, missing 19 -zh-Hans, 336/336, 100%, missing 0 -pt-BR, 64/336, 19%, missing 272 -pl-PL, 3/336, 1%, missing 333 +en-US, 342/342, 100%, missing 0 +de-DE, 319/342, 93%, missing 23 +it-IT, 3/342, 1%, missing 339 +fr-FR, 316/342, 92%, missing 26 +es-ES, 79/342, 23%, missing 263 +ru-RU, 317/342, 93%, missing 25 +zh-Hans, 342/342, 100%, missing 0 +pt-BR, 64/342, 19%, missing 278 +pl-PL, 3/342, 1%, missing 339 diff --git a/Localization/de-DE.hjson b/Localization/de-DE.hjson index 40da152..23bcfd8 100644 --- a/Localization/de-DE.hjson +++ b/Localization/de-DE.hjson @@ -579,6 +579,20 @@ Mods: { Diese Nachrichten sollten erscheinen, wenn ein Boss besiegt wurde oder ein Boss despawnt ist. ''' } + + EnableBossStateToggle: { + // Label: Enable Boss defeated State Toggle + /* Tooltip: + ''' + While enabled,Shift + Right Click a boss in the Boss Log UI toggles its real defeated state + rather than merely marking it as defeated. + ''' */ + } + + // Failed: Failed to toggle defeat state of [{0}]! This entry does not currently support this feature! + // Successed: Toggled [{0}] -> [{1}] ! + // Defeated: Defeated + // Alive: Alive } FeatureConfiguration: { diff --git a/Localization/en-US.hjson b/Localization/en-US.hjson index 5a92da4..58e04de 100644 --- a/Localization/en-US.hjson +++ b/Localization/en-US.hjson @@ -1,4 +1,4 @@ -Mods: { +Mods: { BossChecklist: { Log: { Common: { @@ -583,6 +583,20 @@ Mods: { These messages should appear when a boss has been defeated or a boss has despawned, respectively. ''' } + + EnableBossStateToggle: { + Label: Enable Boss defeated State Toggle + Tooltip: + ''' + While enabled,Shift + Right Click a boss in the Boss Log UI toggles its real defeated state + rather than merely marking it as defeated. + ''' + } + + Failed: Failed to toggle defeat state of [{0}]! This entry does not currently support this feature! + Successed: Toggled [{0}] -> [{1}] ! + Defeated: Defeated + Alive: Alive } FeatureConfiguration: { diff --git a/Localization/es-ES.hjson b/Localization/es-ES.hjson index f1be78e..6356e19 100644 --- a/Localization/es-ES.hjson +++ b/Localization/es-ES.hjson @@ -579,6 +579,20 @@ Mods: { These messages should appear when a boss has been defeated or a boss has despawned, respectively. ''' */ } + + EnableBossStateToggle: { + // Label: Enable Boss defeated State Toggle + /* Tooltip: + ''' + While enabled,Shift + Right Click a boss in the Boss Log UI toggles its real defeated state + rather than merely marking it as defeated. + ''' */ + } + + // Failed: Failed to toggle defeat state of [{0}]! This entry does not currently support this feature! + // Successed: Toggled [{0}] -> [{1}] ! + // Defeated: Defeated + // Alive: Alive } FeatureConfiguration: { diff --git a/Localization/fr-FR.hjson b/Localization/fr-FR.hjson index 1bf22ee..7c6173e 100644 --- a/Localization/fr-FR.hjson +++ b/Localization/fr-FR.hjson @@ -586,6 +586,20 @@ Mods: { Ces messages devraient apparaître lorsqu'un boss a été vaincu ou lorsqu'un boss a disparu, respectivement. ''' } + + EnableBossStateToggle: { + // Label: Enable Boss defeated State Toggle + /* Tooltip: + ''' + While enabled,Shift + Right Click a boss in the Boss Log UI toggles its real defeated state + rather than merely marking it as defeated. + ''' */ + } + + // Failed: Failed to toggle defeat state of [{0}]! This entry does not currently support this feature! + // Successed: Toggled [{0}] -> [{1}] ! + // Defeated: Defeated + // Alive: Alive } FeatureConfiguration: { diff --git a/Localization/it-IT.hjson b/Localization/it-IT.hjson index abc7eeb..2080ec8 100644 --- a/Localization/it-IT.hjson +++ b/Localization/it-IT.hjson @@ -583,6 +583,20 @@ Mods: { These messages should appear when a boss has been defeated or a boss has despawned, respectively. ''' */ } + + EnableBossStateToggle: { + // Label: Enable Boss defeated State Toggle + /* Tooltip: + ''' + While enabled,Shift + Right Click a boss in the Boss Log UI toggles its real defeated state + rather than merely marking it as defeated. + ''' */ + } + + // Failed: Failed to toggle defeat state of [{0}]! This entry does not currently support this feature! + // Successed: Toggled [{0}] -> [{1}] ! + // Defeated: Defeated + // Alive: Alive } FeatureConfiguration: { diff --git a/Localization/pl-PL.hjson b/Localization/pl-PL.hjson index abc7eeb..2080ec8 100644 --- a/Localization/pl-PL.hjson +++ b/Localization/pl-PL.hjson @@ -583,6 +583,20 @@ Mods: { These messages should appear when a boss has been defeated or a boss has despawned, respectively. ''' */ } + + EnableBossStateToggle: { + // Label: Enable Boss defeated State Toggle + /* Tooltip: + ''' + While enabled,Shift + Right Click a boss in the Boss Log UI toggles its real defeated state + rather than merely marking it as defeated. + ''' */ + } + + // Failed: Failed to toggle defeat state of [{0}]! This entry does not currently support this feature! + // Successed: Toggled [{0}] -> [{1}] ! + // Defeated: Defeated + // Alive: Alive } FeatureConfiguration: { diff --git a/Localization/pt-BR.hjson b/Localization/pt-BR.hjson index a91b0af..be820ee 100644 --- a/Localization/pt-BR.hjson +++ b/Localization/pt-BR.hjson @@ -583,6 +583,20 @@ Mods: { These messages should appear when a boss has been defeated or a boss has despawned, respectively. ''' */ } + + EnableBossStateToggle: { + // Label: Enable Boss defeated State Toggle + /* Tooltip: + ''' + While enabled,Shift + Right Click a boss in the Boss Log UI toggles its real defeated state + rather than merely marking it as defeated. + ''' */ + } + + // Failed: Failed to toggle defeat state of [{0}]! This entry does not currently support this feature! + // Successed: Toggled [{0}] -> [{1}] ! + // Defeated: Defeated + // Alive: Alive } FeatureConfiguration: { diff --git a/Localization/ru-RU.hjson b/Localization/ru-RU.hjson index 95af5b2..3add053 100644 --- a/Localization/ru-RU.hjson +++ b/Localization/ru-RU.hjson @@ -582,6 +582,20 @@ Mods: { Эти сообщения должны появляться при победе над боссом или при его исчезновении, соответственно. ''' } + + EnableBossStateToggle: { + // Label: Enable Boss defeated State Toggle + /* Tooltip: + ''' + While enabled,Shift + Right Click a boss in the Boss Log UI toggles its real defeated state + rather than merely marking it as defeated. + ''' */ + } + + // Failed: Failed to toggle defeat state of [{0}]! This entry does not currently support this feature! + // Successed: Toggled [{0}] -> [{1}] ! + // Defeated: Defeated + // Alive: Alive } FeatureConfiguration: { diff --git a/Localization/zh-Hans.hjson b/Localization/zh-Hans.hjson index 9331703..839ba01 100644 --- a/Localization/zh-Hans.hjson +++ b/Localization/zh-Hans.hjson @@ -1,4 +1,4 @@ -Mods: { +Mods: { BossChecklist: { Log: { Common: { @@ -583,6 +583,20 @@ Mods: { 这些信息应该分别在Boss被击败或Boss消失时出现. ''' } + + EnableBossStateToggle: { + Label: 启用Boss击败状态切换功能 + Tooltip: + ''' + 启用后,如果在Boss日志UI中 Shift + 右键 Boss可以切换其真实击败状态 + 而非仅仅标记为击败 + ''' + } + + Failed: 切换 [{0}] 击败状态失败!该Boss暂未支持该功能! + Successed: 成功切换:[{0}] -> [{1}] + Defeated: 已击败 + Alive: 未击败 } FeatureConfiguration: { diff --git a/Networking.cs b/Networking.cs index 6bd7a0a..557b2a2 100644 --- a/Networking.cs +++ b/Networking.cs @@ -1,6 +1,8 @@ using BossChecklist.Systems; +using Microsoft.Xna.Framework; using Terraria; using Terraria.ID; +using Terraria.Localization; using Terraria.ModLoader; namespace BossChecklist @@ -18,7 +20,9 @@ enum PacketMessageType : byte { SendWorldRecordsFromServerToPlayer, UpdateWorldRecordsToAllPlayers, ResetPlayerRecordForServer, - ResetTrackers + ResetTrackers, + RequestBossStateToggle, // Client --> Server + SyncBossState, // Server --> All Clients } internal enum ClientMessageType : byte { @@ -65,5 +69,38 @@ public static void RequestMarkedEntryUpdate(string Key = null, bool mark = true) } packet.Send(); // Multiplayer --> Server } + + + internal static bool TryApplyBossStateToggle(string bossKey, bool downed) { + + EntryInfo entry = BossChecklist.bossTracker.FindEntryFromKey(bossKey); + + if (entry is null || entry.setDowned is null) + return false; + + entry.setDowned(downed); + BossLogSystem.MarkedEntries.Remove(bossKey); + + return true; // if true means toggle success + } + + public static void RequestBossStateToggle(string bossKey, bool downed) { + if (Main.netMode == NetmodeID.SinglePlayer) { + if(!TryApplyBossStateToggle(bossKey, downed)) { + Main.NewText(Language.GetTextValue("Mods.BossChecklist.Configs.DebugTools.Failed", BossChecklist.bossTracker.FindEntryFromKey(bossKey).name), Color.Red); + } + return; + } + + else if (Main.netMode != NetmodeID.MultiplayerClient) + return; + else { + ModPacket packet = BossChecklist.instance.GetPacket(); + packet.Write((byte)PacketMessageType.RequestBossStateToggle); + packet.Write(bossKey); + packet.Write(downed); + packet.Send(); + } + } } } diff --git a/UIElements/BossLogUIElements.cs b/UIElements/BossLogUIElements.cs index 3079d2d..dd1ab88 100644 --- a/UIElements/BossLogUIElements.cs +++ b/UIElements/BossLogUIElements.cs @@ -2,6 +2,7 @@ using BossChecklist.Systems; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; using ReLogic.Content; using ReLogic.Graphics; using ReLogic.OS; @@ -1298,13 +1299,24 @@ public override void RightClick(UIMouseEvent evt) { } } else { - // Entries must not already be downed to add/remove them from the MarkedEntries list - // Entries that are downed will automatically be removed from the lsit when the TableOfContents list is generated - if (BossLogSystem.MarkedEntries.Contains(entry.Key)) { - BossLogSystem.MarkedEntries.Remove(entry.Key); + + bool shiftHeld = Main.keyState.IsKeyDown(Keys.LeftShift) || Main.keyState.IsKeyDown(Keys.RightShift); + + if (shiftHeld && BossChecklist.BossLogConfig.Debug.EnableBossStateToggle) { + bool newState = !entry.downed(); + + Networking.RequestBossStateToggle(entry.Key, newState); } else { - BossLogSystem.MarkedEntries.Add(entry.Key); + // Entries must not already be downed to add/remove them from the MarkedEntries list [YuBell: fixed this] + // Entries that are downed will automatically be removed from the lsit when the TableOfContents list is generated + if (BossLogSystem.MarkedEntries.Contains(entry.Key)) { + BossLogSystem.MarkedEntries.Remove(entry.Key); + } + else { + if (!entry.downed()) // if this boss is already downed,it shouldn't be mark as downed + BossLogSystem.MarkedEntries.Add(entry.Key); + } } Networking.RequestMarkedEntryUpdate(entry.Key, entry.MarkedAsDowned);