using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace SoulHarvest.Common;
internal class BossSoulParticipationSystem : ModSystem
{
private static readonly bool[] TwinParticipants = new bool[Main.maxPlayers];
private static readonly bool[] EaterParticipants = new bool[Main.maxPlayers];
private static readonly bool[] BrainParticipants = new bool[Main.maxPlayers];
private static readonly bool[] GolemParticipants = new bool[Main.maxPlayers];
private static readonly bool[] MoonLordParticipants = new bool[Main.maxPlayers];
private static int twinEncounterLifeMax;
private static int eaterEncounterLifeMax;
private static int brainEncounterLifeMax;
private static int golemEncounterLifeMax;
private static int moonLordEncounterLifeMax;
public override void OnWorldUnload()
{
Clear(TwinParticipants);
Clear(EaterParticipants);
Clear(BrainParticipants);
Clear(GolemParticipants);
Clear(MoonLordParticipants);
twinEncounterLifeMax = 0;
eaterEncounterLifeMax = 0;
brainEncounterLifeMax = 0;
golemEncounterLifeMax = 0;
moonLordEncounterLifeMax = 0;
}
public override void PostUpdateWorld()
{
int twinLife = SumActiveLifeMax(NPCID.Retinazer, NPCID.Spazmatism);
if (twinLife > 0)
twinEncounterLifeMax = System.Math.Max(twinEncounterLifeMax, twinLife);
else
{
Clear(TwinParticipants);
twinEncounterLifeMax = 0;
}
int eaterLife = SumActiveLifeMax(NPCID.EaterofWorldsBody, NPCID.EaterofWorldsHead, NPCID.EaterofWorldsTail);
if (eaterLife > 0)
eaterEncounterLifeMax = System.Math.Max(eaterEncounterLifeMax, eaterLife);
else
{
Clear(EaterParticipants);
eaterEncounterLifeMax = 0;
}
if (!TrackEncounterLife(ref brainEncounterLifeMax, NPCID.BrainofCthulhu, NPCID.Creeper))
Clear(BrainParticipants);
if (!TrackEncounterLife(ref golemEncounterLifeMax, NPCID.Golem, NPCID.GolemHead, NPCID.GolemHeadFree))
Clear(GolemParticipants);
if (!TrackEncounterLife(ref moonLordEncounterLifeMax, NPCID.MoonLordCore, NPCID.MoonLordHead, NPCID.MoonLordHand))
Clear(MoonLordParticipants);
}
internal static void RecordCompositeBossHit(NPC npc, int playerIndex)
{
if (playerIndex < 0 || playerIndex >= Main.maxPlayers)
return;
if (npc.type is NPCID.Retinazer or NPCID.Spazmatism)
TwinParticipants[playerIndex] = true;
else if (npc.type is NPCID.EaterofWorldsBody or NPCID.EaterofWorldsHead or NPCID.EaterofWorldsTail)
EaterParticipants[playerIndex] = true;
else if (npc.type is NPCID.BrainofCthulhu or NPCID.Creeper)
BrainParticipants[playerIndex] = true;
else if (npc.type is NPCID.Golem or NPCID.GolemHead or NPCID.GolemHeadFree)
GolemParticipants[playerIndex] = true;
else if (npc.type is NPCID.MoonLordCore or NPCID.MoonLordHead or NPCID.MoonLordHand)
MoonLordParticipants[playerIndex] = true;
}
internal static bool TryTakeCompositeParticipants(NPC npc, out bool[] participants, out int encounterLifeMax)
{
participants = [];
encounterLifeMax = 0;
switch (npc.type)
{
case NPCID.Retinazer:
if (NPC.AnyNPCs(NPCID.Spazmatism))
return false;
participants = Take(TwinParticipants);
encounterLifeMax = System.Math.Max(npc.lifeMax, twinEncounterLifeMax);
twinEncounterLifeMax = 0;
return true;
case NPCID.Spazmatism:
if (NPC.AnyNPCs(NPCID.Retinazer))
return false;
participants = Take(TwinParticipants);
encounterLifeMax = System.Math.Max(npc.lifeMax, twinEncounterLifeMax);
twinEncounterLifeMax = 0;
return true;
case NPCID.EaterofWorldsBody:
case NPCID.EaterofWorldsHead:
case NPCID.EaterofWorldsTail:
if (NPC.AnyNPCs(NPCID.EaterofWorldsBody) || NPC.AnyNPCs(NPCID.EaterofWorldsHead) || NPC.AnyNPCs(NPCID.EaterofWorldsTail))
return false;
participants = Take(EaterParticipants);
encounterLifeMax = System.Math.Max(npc.lifeMax, eaterEncounterLifeMax);
eaterEncounterLifeMax = 0;
return true;
case NPCID.BrainofCthulhu:
participants = Take(BrainParticipants);
encounterLifeMax = System.Math.Max(npc.lifeMax, brainEncounterLifeMax);
brainEncounterLifeMax = 0;
return true;
case NPCID.Golem:
participants = Take(GolemParticipants);
encounterLifeMax = System.Math.Max(npc.lifeMax, golemEncounterLifeMax);
golemEncounterLifeMax = 0;
return true;
case NPCID.MoonLordCore:
participants = Take(MoonLordParticipants);
encounterLifeMax = System.Math.Max(npc.lifeMax, moonLordEncounterLifeMax);
moonLordEncounterLifeMax = 0;
return true;
default:
return false;
}
}
internal static int GetEncounterLifeMax(NPC npc)
{
int trackedLife = npc.type switch
{
NPCID.BrainofCthulhu => brainEncounterLifeMax,
NPCID.Golem => golemEncounterLifeMax,
NPCID.MoonLordCore => moonLordEncounterLifeMax,
_ => 0
};
return System.Math.Max(npc.lifeMax, trackedLife);
}
private static bool TrackEncounterLife(ref int storedLifeMax, params int[] npcTypes)
{
int currentLifeMax = SumActiveLifeMax(npcTypes);
if (currentLifeMax > 0)
{
storedLifeMax = System.Math.Max(storedLifeMax, currentLifeMax);
return true;
}
else
{
storedLifeMax = 0;
return false;
}
}
private static int SumActiveLifeMax(params int[] npcTypes)
{
int total = 0;
foreach (NPC npc in Main.ActiveNPCs)
{
for (int index = 0; index < npcTypes.Length; index++)
{
if (npc.type != npcTypes[index])
continue;
total = (int)System.Math.Min(int.MaxValue, (long)total + npc.lifeMax);
break;
}
}
return total;
}
private static bool[] Take(bool[] source)
{
bool[] result = (bool[])source.Clone();
Clear(source);
return result;
}
private static void Clear(bool[] values)
{
for (int index = 0; index < values.Length; index++)
values[index] = false;
}
}
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace SoulHarvest.Common;
internal class BossSoulParticipationSystem : ModSystem
{
private static readonly bool[] TwinParticipants = new bool[Main.maxPlayers];
private static readonly bool[] EaterParticipants = new bool[Main.maxPlayers];
private static readonly bool[] BrainParticipants = new bool[Main.maxPlayers];
private static readonly bool[] GolemParticipants = new bool[Main.maxPlayers];
private static readonly bool[] MoonLordParticipants = new bool[Main.maxPlayers];
private static int twinEncounterLifeMax;
private static int eaterEncounterLifeMax;
private static int brainEncounterLifeMax;
private static int golemEncounterLifeMax;
private static int moonLordEncounterLifeMax;
public override void OnWorldUnload()
{
Clear(TwinParticipants);
Clear(EaterParticipants);
Clear(BrainParticipants);
Clear(GolemParticipants);
Clear(MoonLordParticipants);
twinEncounterLifeMax = 0;
eaterEncounterLifeMax = 0;
brainEncounterLifeMax = 0;
golemEncounterLifeMax = 0;
moonLordEncounterLifeMax = 0;
}
public override void PostUpdateWorld()
{
int twinLife = SumActiveLifeMax(NPCID.Retinazer, NPCID.Spazmatism);
if (twinLife > 0)
twinEncounterLifeMax = System.Math.Max(twinEncounterLifeMax, twinLife);
else
{
Clear(TwinParticipants);
twinEncounterLifeMax = 0;
}
int eaterLife = SumActiveLifeMax(NPCID.EaterofWorldsBody, NPCID.EaterofWorldsHead, NPCID.EaterofWorldsTail);
if (eaterLife > 0)
eaterEncounterLifeMax = System.Math.Max(eaterEncounterLifeMax, eaterLife);
else
{
Clear(EaterParticipants);
eaterEncounterLifeMax = 0;
}
if (!TrackEncounterLife(ref brainEncounterLifeMax, NPCID.BrainofCthulhu, NPCID.Creeper))
Clear(BrainParticipants);
if (!TrackEncounterLife(ref golemEncounterLifeMax, NPCID.Golem, NPCID.GolemHead, NPCID.GolemHeadFree))
Clear(GolemParticipants);
if (!TrackEncounterLife(ref moonLordEncounterLifeMax, NPCID.MoonLordCore, NPCID.MoonLordHead, NPCID.MoonLordHand))
Clear(MoonLordParticipants);
}
internal static void RecordCompositeBossHit(NPC npc, int playerIndex)
{
if (playerIndex < 0 || playerIndex >= Main.maxPlayers)
return;
if (npc.type is NPCID.Retinazer or NPCID.Spazmatism)
TwinParticipants[playerIndex] = true;
else if (npc.type is NPCID.EaterofWorldsBody or NPCID.EaterofWorldsHead or NPCID.EaterofWorldsTail)
EaterParticipants[playerIndex] = true;
else if (npc.type is NPCID.BrainofCthulhu or NPCID.Creeper)
BrainParticipants[playerIndex] = true;
else if (npc.type is NPCID.Golem or NPCID.GolemHead or NPCID.GolemHeadFree)
GolemParticipants[playerIndex] = true;
else if (npc.type is NPCID.MoonLordCore or NPCID.MoonLordHead or NPCID.MoonLordHand)
MoonLordParticipants[playerIndex] = true;
}
internal static bool TryTakeCompositeParticipants(NPC npc, out bool[] participants, out int encounterLifeMax)
{
participants = [];
encounterLifeMax = 0;
switch (npc.type)
{
case NPCID.Retinazer:
if (NPC.AnyNPCs(NPCID.Spazmatism))
return false;
participants = Take(TwinParticipants);
encounterLifeMax = System.Math.Max(npc.lifeMax, twinEncounterLifeMax);
twinEncounterLifeMax = 0;
return true;
case NPCID.Spazmatism:
if (NPC.AnyNPCs(NPCID.Retinazer))
return false;
participants = Take(TwinParticipants);
encounterLifeMax = System.Math.Max(npc.lifeMax, twinEncounterLifeMax);
twinEncounterLifeMax = 0;
return true;
case NPCID.EaterofWorldsBody:
case NPCID.EaterofWorldsHead:
case NPCID.EaterofWorldsTail:
if (NPC.AnyNPCs(NPCID.EaterofWorldsBody) || NPC.AnyNPCs(NPCID.EaterofWorldsHead) || NPC.AnyNPCs(NPCID.EaterofWorldsTail))
return false;
participants = Take(EaterParticipants);
encounterLifeMax = System.Math.Max(npc.lifeMax, eaterEncounterLifeMax);
eaterEncounterLifeMax = 0;
return true;
case NPCID.BrainofCthulhu:
participants = Take(BrainParticipants);
encounterLifeMax = System.Math.Max(npc.lifeMax, brainEncounterLifeMax);
brainEncounterLifeMax = 0;
return true;
case NPCID.Golem:
participants = Take(GolemParticipants);
encounterLifeMax = System.Math.Max(npc.lifeMax, golemEncounterLifeMax);
golemEncounterLifeMax = 0;
return true;
case NPCID.MoonLordCore:
participants = Take(MoonLordParticipants);
encounterLifeMax = System.Math.Max(npc.lifeMax, moonLordEncounterLifeMax);
moonLordEncounterLifeMax = 0;
return true;
default:
return false;
}
}
internal static int GetEncounterLifeMax(NPC npc)
{
int trackedLife = npc.type switch
{
NPCID.BrainofCthulhu => brainEncounterLifeMax,
NPCID.Golem => golemEncounterLifeMax,
NPCID.MoonLordCore => moonLordEncounterLifeMax,
_ => 0
};
return System.Math.Max(npc.lifeMax, trackedLife);
}
private static bool TrackEncounterLife(ref int storedLifeMax, params int[] npcTypes)
{
int currentLifeMax = SumActiveLifeMax(npcTypes);
if (currentLifeMax > 0)
{
storedLifeMax = System.Math.Max(storedLifeMax, currentLifeMax);
return true;
}
else
{
storedLifeMax = 0;
return false;
}
}
private static int SumActiveLifeMax(params int[] npcTypes)
{
int total = 0;
foreach (NPC npc in Main.ActiveNPCs)
{
for (int index = 0; index < npcTypes.Length; index++)
{
if (npc.type != npcTypes[index])
continue;
total = (int)System.Math.Min(int.MaxValue, (long)total + npc.lifeMax);
break;
}
}
return total;
}
private static bool[] Take(bool[] source)
{
bool[] result = (bool[])source.Clone();
Clear(source);
return result;
}
private static void Clear(bool[] values)
{
for (int index = 0; index < values.Length; index++)
values[index] = false;
}
}