Files
7d2dXG/Mods/zzz_REBIRTH__Utils/Scripts/Manager/Inactive/ScenarioManagerRebirth.cs
Nathaniel Cosford 062dfab2cd Patched
2025-05-30 01:04:40 +09:30

1144 lines
49 KiB
C#

using Audio;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using static AstarManager;
public class ScenarioManagerRebirth
{
private static ScenarioManagerRebirth instance = null;
private static string SaveDataPath = "";
private static string ModPath = "";
private static float prefabUpdateTick = 0.25f;
private static float prefabUpdateCheck = 0f;
private static float cleanupUpdateTick = 60f;
private static float cleanupUpdateCheck = 0f;
public static List<PurgeKills> purgeKills = new List<PurgeKills>();
public static List<PrefabInfo> ClearedPrefabs = new List<PrefabInfo>();
public static List<PrefabInfo> DiscoveredPrefabs = new List<PrefabInfo>();
public static List<DynamicPrefab> dynamicPrefabs = new List<DynamicPrefab>();
public static bool dynamicPrefabsLoaded = false;
public static bool processingDynamicPrefabs = false;
public class DynamicPrefab
{
public string PrefabName { get; set; }
public Vector3 Position { get; set; }
public Vector3 Size { get; set; }
public int Difficulty { get; set; }
public string Biome { get; set; }
public string Tags { get; set; }
public DynamicPrefab(string prefabName, Vector3 position, Vector3 size, int difficulty, string biome, string tags)
{
PrefabName = prefabName;
Position = position;
Size = size;
Difficulty = difficulty;
Biome = biome;
Tags = tags;
}
}
public class PlayerKillInfo
{
public int PlayerID { get; set; }
public int Kills { get; set; }
public bool Redeemed { get; set; }
}
public class KillInfo
{
public int Kills { get; set; }
public bool Redeemed { get; set; }
}
public class PurgeKills
{
public string Name { get; set; }
public Vector3 Position { get; set; }
public Dictionary<int, KillInfo> Players { get; set; } = new Dictionary<int, KillInfo>(); // Player ID as key, Kills as value
}
public class PrefabInfo
{
public string Name { get; set; }
public Vector3 Position { get; set; }
public Vector3 Size { get; set; }
public int Difficulty { get; set; }
public int EntitiesCleared { get; set; }
public Dictionary<int, string> Players { get; set; } // Player ID as key, player name as value
public string PlayerName { get; set; }
public string Biome { get; set; }
}
public static bool HasInstance => instance != null;
public static ScenarioManagerRebirth Instance
{
get
{
return instance;
}
}
public static void Init()
{
ScenarioManagerRebirth.instance = new ScenarioManagerRebirth();
Log.Out("Starting Scenario Manager");
var mod = ModManager.GetMod("zzz_REBIRTH__Utils", true);
ModPath = mod.Path;
SaveDataPath = SaveDataPath = GameIO.GetUserGameDataDir() + "/RebirthData/Scenarios"; // mod.Path + "/Scenarios";
Directory.CreateDirectory(SaveDataPath);
ClearedPrefabs = new List<PrefabInfo>();
DiscoveredPrefabs = new List<PrefabInfo>();
foreach (KeyValuePair<int, string> biome in RebirthVariables.biomes)
{
int key = biome.Key; // The int key (0, 1, 2, etc.)
string value = biome.Value; // The string value ("pine_forest", "desert", etc.)
RebirthUtilities.AddPurgeBiome(value, 0);
}
//Log.Out("ScenarioManagerRebirth-Init RebirthVariables.purgeBiomes.Count: " + RebirthVariables.purgeBiomes.Count);
LoadScenario("purge");
if ((SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer && !GameManager.IsDedicatedServer) || SingletonMonoBehaviour<ConnectionManager>.Instance.IsSinglePlayer)
{
foreach (var prefab in ScenarioManagerRebirth.ClearedPrefabs)
{
//Log.Out("ScenarioManagerRebirth-Init SCENARIO Purged prefab.Name: " + prefab.Name);
Vector3 vector = new Vector3(prefab.Position.x + prefab.Size.x / 2f, prefab.Position.y, prefab.Position.z + prefab.Size.z / 2f);
NavObject navPurged = NavObjectManager.Instance.RegisterNavObject("purge_waypoint", vector, "purge_waypoint");
if (navPurged != null)
{
navPurged.TrackedPosition = vector;
}
navPurged.trackedPosition = vector;
//navPurged.ForceDisabled = true;
//navPurged.IsActive = false;
}
foreach (var prefab in ScenarioManagerRebirth.DiscoveredPrefabs)
{
//Log.Out("ScenarioManagerRebirth-Init SCENARIO Discovered prefab.Name: " + prefab.Name);
Vector3 vector = new Vector3(prefab.Position.x + prefab.Size.x / 2f, prefab.Position.y, prefab.Position.z + prefab.Size.z / 2f);
NavObject navDiscovered = NavObjectManager.Instance.RegisterNavObject("discovered_waypoint_" + prefab.Difficulty, vector, "discovered_waypoint_" + prefab.Difficulty);
if (navDiscovered != null)
{
navDiscovered.TrackedPosition = vector;
}
navDiscovered.trackedPosition = vector;
}
}
ModEvents.GameUpdate.RegisterHandler(Update);
}
public static bool IsIgnoredPrefab(string prefabName)
{
// Check if the prefabName exists in the ignorePrefabs XML (case-insensitive)
return RebirthVariables.ignorePrefabs
.Descendants("prefab")
.Any(p => p.Attribute("name")?.Value.ToLower() == prefabName.ToLower());
}
public static List<PrefabInfo> GetIgnoredDiscoveredPrefabs()
{
// Create an empty list to hold the matching PrefabInfo objects
List<PrefabInfo> ignoredPrefabs = new List<PrefabInfo>();
// Get the list of prefab names from the ignorePrefabs XML
var ignoredNames = RebirthVariables.ignorePrefabs
.Descendants("prefab")
.Select(p => p.Attribute("name")?.Value)
.Where(n => !string.IsNullOrEmpty(n))
.ToList();
// Filter the DiscoveredPrefabs based on the prefab names in ignorePrefabs
foreach (var prefab in DiscoveredPrefabs)
{
if (ignoredNames.Contains(prefab.Name))
{
//Log.Out("ScenarioManager-Update ignoredPrefabs CLEANUP, prefab.Name: " + prefab.Name);
//Log.Out("ScenarioManager-Update ignoredPrefabs CLEANUP, prefab.Position: " + prefab.Position);
ignoredPrefabs.Add(prefab);
}
}
return ignoredPrefabs;
}
public static void Update()
{
if (GameUtils.IsPlaytesting())
{
return;
}
if ((Time.time - cleanupUpdateCheck) > cleanupUpdateTick)
{
cleanupUpdateCheck = Time.time;
//Log.Out("ScenarioManager-Update CLEANUP, ClearedPrefabs.Count: " + ClearedPrefabs.Count);
//Log.Out("ScenarioManager-Update CLEANUP, DiscoveredPrefabs.Count: " + DiscoveredPrefabs.Count);
List<PrefabInfo> ignoredPrefabs = GetIgnoredDiscoveredPrefabs();
foreach (var prefab in ignoredPrefabs)
{
// Example: remove them from DiscoveredPrefabs
DiscoveredPrefabs.Remove(prefab);
//Log.Out("ScenarioManager-Update ignoredPrefabs CLEANUP, prefab.Name: " + prefab.Name);
Vector3 location = new Vector3(prefab.Position.x + prefab.Size.x / 2f, prefab.Position.y, prefab.Position.z + prefab.Size.z / 2f);
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsSinglePlayer)
{
NavObjectManager.Instance.UnRegisterNavObjectByPosition(location, "discovered_waypoint_" + prefab.Difficulty);
}
else
{
if (!GameManager.IsDedicatedServer)
{
NavObjectManager.Instance.UnRegisterNavObjectByPosition(location, "discovered_waypoint_" + prefab.Difficulty);
}
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage((NetPackage)NetPackageManager.GetPackage<NetPackageUnregisterNavObject>().Setup("discovered_waypoint_" + prefab.Difficulty, location.x, location.y, location.z), false);
}
}
SaveDiscovered();
var matchingPrefabs = DiscoveredPrefabs
.Where(discovered => ClearedPrefabs.Any(cleared =>
cleared.Name == discovered.Name && cleared.Position == discovered.Position))
.ToList();
// Optional: Log the number of matching prefabs found
//Log.Out($"ScenarioManager-Update CLEANUP: {matchingPrefabs.Count} discovered prefabs already cleared.");
// Perform any other cleanup actions or processing with matchingPrefabs
foreach (var prefab in matchingPrefabs)
{
// Example: remove them from DiscoveredPrefabs
DiscoveredPrefabs.Remove(prefab);
//Log.Out("ScenarioManager-Update CLEANUP, prefab.Name: " + prefab.Name);
Vector3 location = new Vector3(prefab.Position.x + prefab.Size.x / 2f, prefab.Position.y, prefab.Position.z + prefab.Size.z / 2f);
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsSinglePlayer)
{
NavObjectManager.Instance.UnRegisterNavObjectByPosition(location, "discovered_waypoint_" + prefab.Difficulty);
}
else
{
if (!GameManager.IsDedicatedServer)
{
NavObjectManager.Instance.UnRegisterNavObjectByPosition(location, "discovered_waypoint_" + prefab.Difficulty);
}
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage((NetPackage)NetPackageManager.GetPackage<NetPackageUnregisterNavObject>().Setup("discovered_waypoint_" + prefab.Difficulty, location.x, location.y, location.z), false);
}
}
}
if ((Time.time - prefabUpdateCheck) > prefabUpdateTick)
{
prefabUpdateCheck = Time.time;
if (dynamicPrefabsLoaded)
{
/*Log.Out("ScenarioManager-Update LIST OF PREFABS LOADED, dynamicPrefabs.Count: " + dynamicPrefabs.Count);
if (dynamicPrefabs.Count > 0)
{
GameManager.Instance.StartCoroutine(RebirthUtilities.processDynamicPrefabs("pine_forest"));
GameManager.Instance.StartCoroutine(RebirthUtilities.processDynamicPrefabs("desert"));
GameManager.Instance.StartCoroutine(RebirthUtilities.processDynamicPrefabs("snow"));
GameManager.Instance.StartCoroutine(RebirthUtilities.processDynamicPrefabs("wasteland"));
GameManager.Instance.StartCoroutine(RebirthUtilities.processDynamicPrefabs("burnt_forest"));
}
else
{
prefabUpdateTick = 5f;
}*/
}
else
{
if (RebirthVariables.testPurge)
Log.Out("ScenarioManager-Update GET LIST OF PREFABS");
System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
watch.Start();
int numPrefabs = 0;
int numPrefabs2 = 0;
int numPrefabs3 = 0;
List<PrefabInstance> tempDynamicPrefabs = GameManager.Instance.GetDynamicPrefabDecorator()?.GetDynamicPrefabs();
if (tempDynamicPrefabs != null)
{
if (RebirthVariables.testPurge)
Log.Out("ScenarioManager-Update RETRIEVED BASE LIST OF DYNAMIC PREFABS, tempDynamicPrefabs.Count: " + tempDynamicPrefabs.Count);
if (tempDynamicPrefabs.Count > 0)
{
foreach (PrefabInstance _prefabInstance in tempDynamicPrefabs)
{
numPrefabs++;
//if (!_prefabInstance.prefab.PrefabName.ToLower().Contains("_tile_") && !_prefabInstance.prefab.Tags.Test_AnySet(FastTags<TagGroup.Poi>.Parse("rwgonly,streettile,part,hideui")))
if (_prefabInstance.prefab.SleeperVolumes.Count > 0 && !_prefabInstance.prefab.Tags.Test_AnySet(FastTags<TagGroup.Poi>.Parse("rwgonly,streettile,hideui")))
{
numPrefabs2++;
BiomeDefinition biomeAt = GameManager.Instance.World.ChunkCache.ChunkProvider.GetBiomeProvider().GetBiomeAt(_prefabInstance.boundingBoxPosition.x, _prefabInstance.boundingBoxPosition.z);
if (biomeAt != null)
{
numPrefabs3++;
Vector3 location = new Vector3(_prefabInstance.boundingBoxPosition.x, _prefabInstance.boundingBoxPosition.y, _prefabInstance.boundingBoxPosition.z);
if (RebirthVariables.testPurge)
{
Log.Out("ScenarioManager-Update _prefabInstance.prefab.PrefabName: " + _prefabInstance.prefab.PrefabName);
Log.Out("ScenarioManager-Update _prefabInstance.boundingBoxPosition: " + _prefabInstance.boundingBoxPosition);
Log.Out("ScenarioManager-Update _prefabInstance.boundingBoxSize: " + _prefabInstance.boundingBoxSize);
Log.Out("ScenarioManager-Update _prefabInstance.prefab.Tags: " + _prefabInstance.prefab.Tags);
Log.Out("ScenarioManager-Update biomeAt.m_sBiomeName: " + biomeAt.m_sBiomeName);
Log.Out("ScenarioManager-Update _prefabInstance.prefab.SleeperVolumes.Count: " + _prefabInstance.prefab.SleeperVolumes.Count);
}
if (!IsIgnoredPrefab(_prefabInstance.prefab.PrefabName))
{
AddDynamicPrefab(new DynamicPrefab(_prefabInstance.prefab.PrefabName, location, new Vector3(_prefabInstance.boundingBoxSize.x, _prefabInstance.boundingBoxSize.y, _prefabInstance.boundingBoxSize.z), _prefabInstance.prefab.DifficultyTier, biomeAt.m_sBiomeName, _prefabInstance.prefab.Tags.ToString()));
}
}
}
}
if (!RebirthVariables.purgePrefabCount)
{
RebirthVariables.purgePrefabCount = true;
foreach (KeyValuePair<int, string> biome in RebirthVariables.biomes)
{
int key = biome.Key; // The int key (0, 1, 2, etc.)
string value = biome.Value; // The string value ("pine_forest", "desert", etc.)
for (int i = 0; i <= 6; i++)
{
int clearedPrefabs = GetClearedPrefabCount(value, i);
RebirthUtilities.AddSpawnedPrefab(value, ScenarioManagerRebirth.RetrieveTotalBiomePrefabs(value, i), i);
if (RebirthVariables.testPurge)
Log.Out($"ScenarioManager-Update {value} PREFABS, DIFFICULTY {i}: {RebirthUtilities.GetSpawnedPrefab(value, i)} / cleared: {clearedPrefabs}");
}
}
}
dynamicPrefabsLoaded = true;
}
}
//watch.Stop();
//Log.Out("ScenarioManager-Update time to process: " + watch.ElapsedMilliseconds + " ms");
if (RebirthVariables.testPurge)
{
Log.Out("ScenarioManager-Update numPrefabs: " + numPrefabs);
Log.Out("ScenarioManager-Update numPrefabs2: " + numPrefabs2);
Log.Out("ScenarioManager-Update numPrefabs3: " + numPrefabs3);
}
}
}
}
public static void AddDynamicPrefab(DynamicPrefab prefab)
{
dynamicPrefabs.Add(prefab);
}
// Remove from the list using prefabName and position
public static bool RemoveDynamicPrefab(string prefabName, Vector3 position)
{
var prefabToRemove = dynamicPrefabs.Find(p => p.PrefabName == prefabName && p.Position == position);
if (prefabToRemove != null)
{
dynamicPrefabs.Remove(prefabToRemove);
return true;
}
return false;
}
// Retrieve the first entry for a given difficulty and biome
public static DynamicPrefab RetrieveDynamicPrefab(int difficulty, string biome)
{
return dynamicPrefabs.Find(p => p.Difficulty == difficulty && p.Biome == biome);
}
public static DynamicPrefab RetrieveDynamicPrefab(List<DynamicPrefab> tempDynamicPrefabs, int difficulty, string biome)
{
return tempDynamicPrefabs.Find(p => p.Difficulty == difficulty && p.Biome == biome);
}
public static List<DynamicPrefab> RetrieveDynamicPrefabs(string biome)
{
// Filter prefabs based on the biome provided
List<DynamicPrefab> filteredPrefabs = dynamicPrefabs.FindAll(prefab => prefab.Biome == biome);
return filteredPrefabs;
}
public static List<DynamicPrefab> RetrieveDynamicPrefabsFromDistance(string biome, Vector3 playerPosition, float distance, int difficulty)
{
List<DynamicPrefab> filteredPrefabs = dynamicPrefabs.FindAll(prefab => prefab.Biome == biome && prefab.Difficulty == difficulty);
foreach (var prefab in dynamicPrefabs)
{
// Calculate the distance between the prefab position and the player's position
Vector3 location = new Vector3(prefab.Position.x + prefab.Size.x / 2f, prefab.Position.y, prefab.Position.z + prefab.Size.z / 2f);
float distanceToPrefab = Vector3.Distance(location, playerPosition);
// Check if the prefab is within the specified distance
if (distanceToPrefab > distance)
{
filteredPrefabs.Remove(prefab);
}
}
return filteredPrefabs;
}
public static int RetrieveTotalBiomePrefabs(string biome, int difficulty)
{
List<DynamicPrefab> filteredPrefabs = dynamicPrefabs.FindAll(prefab => prefab.Biome == biome && prefab.Difficulty == difficulty);
//Log.Out("ScenarioManagerRebirth-RetrieveTotalBiomePrefabs filteredPrefabs.Count: " + filteredPrefabs.Count);
return filteredPrefabs.Count;
}
private static void LoadScenario(string scenario)
{
string scenarioPath = $"{SaveDataPath}/{GamePrefs.GetString(EnumGamePrefs.GameWorld)}/{GamePrefs.GetString(EnumGamePrefs.GameName)}";
Directory.CreateDirectory(scenarioPath);
string scenarioFilePath = $"{scenarioPath}/" + scenario + ".xml";
string discoveredFilePath = $"{scenarioPath}/discoveredPrefabs.xml";
string purgeKillsFilePath = $"{scenarioPath}/purgeKillsInfo.xml";
bool exists = System.IO.File.Exists(scenarioFilePath);
bool createNew = false;
if (exists)
{
//Log.Out("ScenarioManagerRebirth-LoadScenario SCENARIO FILE EXISTS");
int currentDay = GameUtils.WorldTimeToDays(GameManager.Instance.World.worldTime);
//Log.Out("ScenarioManagerRebirth-LoadScenario currentDay: " + currentDay);
float currentTimeOfDayHours = GameUtils.WorldTimeToHours(GameManager.Instance.World.worldTime);
//Log.Out("ScenarioManagerRebirth-LoadScenario currentTimeOfDayHours: " + currentTimeOfDayHours);
float currentTimeOfDayMinutes = GameUtils.WorldTimeToMinutes(GameManager.Instance.World.worldTime);
//Log.Out("ScenarioManagerRebirth-LoadScenario currentTimeOfDayMinutes: " + currentTimeOfDayMinutes);
if (currentDay == 1 && currentTimeOfDayHours == 7 && currentTimeOfDayMinutes < 20)
{
//Log.Out("ScenarioManagerRebirth-LoadScenario EARLY MORNING");
try
{
Directory.Delete(scenarioFilePath);
}
catch { }
if (scenario == "purge")
{
try
{
Directory.Delete(purgeKillsFilePath);
}
catch { }
}
createNew = true;
}
}
else
{
//Log.Out("ScenarioManagerRebirth-LoadScenario SCENARIO FILE DOES NOT EXIST");
createNew = true;
}
if (createNew)
{
//Log.Out("ScenarioManagerRebirth-LoadScenario CREATE NEW FILE");
SaveScenario(scenario); // Save an empty file if it doesn't exist
SaveDiscovered();
if (scenario == "purge")
{
SavePurgeKills();
}
return;
}
//Log.Out("ScenarioManagerRebirth-LoadScenario LOAD EXISTING FILE");
if (scenario == "purge")
{
XDocument xmlDoc = XDocument.Load(scenarioFilePath);
ClearedPrefabs = (from prefab in xmlDoc.Root.Elements("Prefab")
select new PrefabInfo
{
Name = prefab.Element("Name").Value,
Position = new Vector3(
float.Parse(prefab.Element("Position").Element("X").Value),
float.Parse(prefab.Element("Position").Element("Y").Value),
float.Parse(prefab.Element("Position").Element("Z").Value)),
Size = new Vector3(
float.Parse(prefab.Element("Size").Element("X").Value),
float.Parse(prefab.Element("Size").Element("Y").Value),
float.Parse(prefab.Element("Size").Element("Z").Value)),
Difficulty = int.Parse(prefab.Element("Difficulty").Value),
EntitiesCleared = int.Parse(prefab.Element("EntitiesCleared").Value),
Players = prefab.Element("Players").Elements("Player")
.ToDictionary(p => int.Parse(p.Element("ID").Value), p => p.Element("Name").Value),
Biome = prefab.Element("Biome").Value
}).ToList();
if (File.Exists(discoveredFilePath))
{
xmlDoc = XDocument.Load(discoveredFilePath);
DiscoveredPrefabs = (from prefab in xmlDoc.Root.Elements("Prefab")
select new PrefabInfo
{
Name = prefab.Element("Name").Value,
Position = new Vector3(
float.Parse(prefab.Element("Position").Element("X").Value),
float.Parse(prefab.Element("Position").Element("Y").Value),
float.Parse(prefab.Element("Position").Element("Z").Value)),
Size = new Vector3(
float.Parse(prefab.Element("Size").Element("X").Value),
float.Parse(prefab.Element("Size").Element("Y").Value),
float.Parse(prefab.Element("Size").Element("Z").Value)),
Difficulty = int.Parse(prefab.Element("Difficulty").Value),
EntitiesCleared = int.Parse(prefab.Element("EntitiesCleared").Value),
Players = prefab.Element("Players").Elements("Player")
.ToDictionary(p => int.Parse(p.Element("ID").Value), p => p.Element("Name").Value),
Biome = prefab.Element("Biome").Value
}).ToList();
}
if (File.Exists(purgeKillsFilePath))
{
xmlDoc = XDocument.Load(purgeKillsFilePath);
purgeKills = (from purgeKill in xmlDoc.Root.Elements("PurgeKill")
select new PurgeKills
{
Name = purgeKill.Element("Name").Value,
Position = new Vector3(
float.Parse(purgeKill.Element("Position").Element("X").Value),
float.Parse(purgeKill.Element("Position").Element("Y").Value),
float.Parse(purgeKill.Element("Position").Element("Z").Value)),
Players = purgeKill.Element("Players").Elements("Player")
.ToDictionary(p => int.Parse(p.Element("ID").Value), p => new KillInfo
{
Kills = int.Parse(p.Element("Kills").Value),
Redeemed = bool.Parse(p.Element("Redeemed").Value) // Load Redeemed value
})
}).ToList();
}
}
}
public static void SaveScenario(string scenario)
{
string scenarioPath = $"{SaveDataPath}/{GamePrefs.GetString(EnumGamePrefs.GameWorld)}/{GamePrefs.GetString(EnumGamePrefs.GameName)}";
Directory.CreateDirectory(scenarioPath);
string scenarioFilePath = $"{scenarioPath}/" + scenario + ".xml";
XElement root = new XElement("Prefabs",
from prefab in ClearedPrefabs
select new XElement("Prefab",
new XElement("Name", prefab.Name),
new XElement("Position",
new XElement("X", prefab.Position.x),
new XElement("Y", prefab.Position.y),
new XElement("Z", prefab.Position.z)),
new XElement("Size",
new XElement("X", prefab.Size.x),
new XElement("Y", prefab.Size.y),
new XElement("Z", prefab.Size.z)),
new XElement("Difficulty", prefab.Difficulty),
new XElement("EntitiesCleared", prefab.EntitiesCleared),
new XElement("Players",
from player in prefab.Players
select new XElement("Player",
new XElement("ID", player.Key),
new XElement("Name", player.Value))),
new XElement("Biome", prefab.Biome)
));
XDocument xmlDoc = new XDocument(root);
xmlDoc.Save(scenarioFilePath);
}
public static void SaveDiscovered()
{
string scenarioPath = $"{SaveDataPath}/{GamePrefs.GetString(EnumGamePrefs.GameWorld)}/{GamePrefs.GetString(EnumGamePrefs.GameName)}";
Directory.CreateDirectory(scenarioPath);
string filePath = $"{scenarioPath}/discoveredPrefabs.xml";
XElement root = new XElement("Prefabs",
from prefab in DiscoveredPrefabs
select new XElement("Prefab",
new XElement("Name", prefab.Name),
new XElement("Position",
new XElement("X", prefab.Position.x),
new XElement("Y", prefab.Position.y),
new XElement("Z", prefab.Position.z)),
new XElement("Size",
new XElement("X", prefab.Size.x),
new XElement("Y", prefab.Size.y),
new XElement("Z", prefab.Size.z)),
new XElement("Difficulty", prefab.Difficulty),
new XElement("EntitiesCleared", prefab.EntitiesCleared),
new XElement("Players",
from player in prefab.Players
select new XElement("Player",
new XElement("ID", player.Key),
new XElement("Name", player.Value))),
new XElement("Biome", prefab.Biome)
));
XDocument xmlDoc = new XDocument(root);
xmlDoc.Save(filePath);
}
// PURGE KILLS HELPERS
public static int GetTotalPurgeKills(string name, Vector3 position)
{
// Get the list of players from the GetPurgeKillPlayers function
var players = GetPurgeKillPlayers(name, position);
// Sum the total kills of all players
return players.Sum(p => p.Kills);
}
public static List<PlayerKillInfo> GetPurgeKillPlayers(string name, Vector3 position)
{
var purgeKill = GetPurgeKillEntry(name, position);
if (purgeKill != null)
{
// Convert the Players dictionary to a list of PlayerKillInfo
return purgeKill.Players.Select(p => new PlayerKillInfo
{
PlayerID = p.Key,
Kills = p.Value.Kills, // Access kills from KillInfo
Redeemed = p.Value.Redeemed // Access redeemed status from KillInfo
}).ToList();
}
return new List<PlayerKillInfo>(); // Return an empty list if no matching PurgeKill entry is found
}
public static List<PurgeKills> GetPurgeKillEntries(int playerID)
{
return purgeKills.Where(pk => pk.Players.ContainsKey(playerID)).ToList();
}
private static PurgeKills GetPurgeKillEntry(string name, Vector3 position)
{
return purgeKills.FirstOrDefault(pk => pk.Name == name && pk.Position == position);
}
private static bool PurgeKillExists(string name, Vector3 position)
{
return purgeKills.Any(pk => pk.Name == name && pk.Position == position);
}
public static int GetTotalKills(int playerID)
{
// Sum the total kills for the playerID across all PurgeKills entries
int totalKills = purgeKills
.Where(purgeKill => purgeKill.Players.ContainsKey(playerID)) // Filter entries that have this playerID
.Sum(purgeKill => purgeKill.Players[playerID].Kills); // Sum the kills for this playerID
return totalKills;
}
public static List<PurgeKills> GetKills(string name, Vector3 position, int playerID)
{
return purgeKills.Where(pk => pk.Name == name && pk.Position == position && pk.Players.ContainsKey(playerID)).ToList();
}
public static bool RemoveKills(string name, Vector3 position, int playerID)
{
var purgeKill = GetPurgeKillEntry(name, position);
if (purgeKill != null && purgeKill.Players.ContainsKey(playerID))
{
purgeKill.Players.Remove(playerID);
if (purgeKill.Players.Count == 0)
{
purgeKills.Remove(purgeKill);
}
SavePurgeKills();
return true;
}
return false;
}
public static (int numKills, int numRedeemableKills) AddKill(string name, Vector3 position, int playerID)
{
var purgeKill = GetPurgeKillEntry(name, position);
if (purgeKill == null)
{
purgeKill = new PurgeKills
{
Name = name,
Position = position
};
purgeKills.Add(purgeKill);
}
if (!purgeKill.Players.ContainsKey(playerID))
{
purgeKill.Players[playerID] = new KillInfo { Kills = 0, Redeemed = false }; // Initialize with default values
}
purgeKill.Players[playerID].Kills++;
SavePurgeKills();
int numKills = GetCurrentPurgeKills(playerID);
int numRedeemableKills = GetCurrentRedeemablePurgeKills(playerID);
//Log.Out("ScenarioManagerRebirth-AddKill numKills: " + numKills);
//Log.Out("ScenarioManagerRebirth-AddKill numRedeemableKills: " + numRedeemableKills);
return (numKills, numRedeemableKills);
}
public static bool RedeemKills(string name, Vector3 position, int playerID)
{
// Find the matching PurgeKill entry
var purgeKill = GetPurgeKillEntry(name, position);
if (purgeKill != null && purgeKill.Players.ContainsKey(playerID))
{
// Check if the player has any kills
var killInfo = purgeKill.Players[playerID];
if (killInfo != null && !killInfo.Redeemed) // If not already redeemed
{
killInfo.Redeemed = true; // Mark as redeemed
SavePurgeKills(); // Save the updated kills
return true; // Return true if the operation was successful
}
}
return false; // Return false if the operation failed
}
public static int AutoRedeemKills(int playerID)
{
int totalKills = 0;
// Loop through all purge kills
foreach (var purgeKill in purgeKills)
{
// Check if the player is in the current PurgeKill entry
if (purgeKill.Players.ContainsKey(playerID) && IsPrefabCleared(purgeKill.Name, purgeKill.Position))
{
var killInfo = purgeKill.Players[playerID];
// If the kill entry was redeemed, reset it and add kills to total
if (!killInfo.Redeemed)
{
killInfo.Redeemed = true; // Reset the redeemed flag
totalKills += killInfo.Kills; // Add kills to the total count
}
}
}
// Save updated data
SavePurgeKills();
return totalKills; // Return total number of kills that were updated
}
public static int GetCurrentPurgeKills(int playerID)
{
int totalKills = 0;
// Loop through all purge kills
foreach (var purgeKill in purgeKills)
{
// Check if the player is in the current PurgeKill entry
if (purgeKill.Players.ContainsKey(playerID))
{
var killInfo = purgeKill.Players[playerID];
// If the kill entry was redeemed, reset it and add kills to total
if (!killInfo.Redeemed)
{
totalKills += killInfo.Kills; // Add kills to the total count
}
}
}
return totalKills;
}
public static int GetCurrentRedeemablePurgeKills(int playerID)
{
int totalKills = 0;
// Loop through all purge kills
foreach (var purgeKill in purgeKills)
{
// Check if the player is in the current PurgeKill entry
if (purgeKill.Players.ContainsKey(playerID) && !IsPrefabCleared(purgeKill.Name, purgeKill.Position))
{
var killInfo = purgeKill.Players[playerID];
// If the kill entry was redeemed, reset it and add kills to total
if (!killInfo.Redeemed)
{
totalKills += killInfo.Kills; // Add kills to the total count
}
}
}
return totalKills;
}
private static void SavePurgeKills()
{
if (GameManager.Instance.World.IsEditor())
{
return;
}
string scenarioPath = $"{SaveDataPath}/{GamePrefs.GetString(EnumGamePrefs.GameWorld)}/{GamePrefs.GetString(EnumGamePrefs.GameName)}";
string purgeKillsFilePath = $"{scenarioPath}/purgeKillsInfo.xml";
XElement root = new XElement("PurgeKills",
from purgeKill in purgeKills
select new XElement("PurgeKill",
new XElement("Name", purgeKill.Name),
new XElement("Position",
new XElement("X", purgeKill.Position.x),
new XElement("Y", purgeKill.Position.y),
new XElement("Z", purgeKill.Position.z)),
new XElement("Players",
from player in purgeKill.Players
select new XElement("Player",
new XElement("ID", player.Key),
new XElement("Kills", player.Value.Kills), // Save kills
new XElement("Redeemed", player.Value.Redeemed) // Save redeemed status
))
));
XDocument xmlDoc = new XDocument(root);
xmlDoc.Save(purgeKillsFilePath);
}
// PREFAB INFO HELPERS
public static string GetFirstPlayerName(PrefabInfo prefabInfo)
{
if (prefabInfo.Players != null && prefabInfo.Players.Count > 0)
{
// Get the first player's name (the first value from the dictionary)
return prefabInfo.Players.Values.First();
}
return null; // Return null if the dictionary is empty or not set
}
public static void AddPrefab(string name, Vector3 position, Vector3 size, int difficulty, int entitiesCleared, Dictionary<int, string> players, string biome)
{
if (IsPrefabCleared(name, position))
{
return;
}
PrefabInfo newPrefab = new PrefabInfo
{
Name = name,
Position = position,
Size = size,
Difficulty = difficulty,
EntitiesCleared = entitiesCleared,
Players = players,
Biome = biome
};
Vector3 vector = new Vector3(newPrefab.Position.x + newPrefab.Size.x / 2f, newPrefab.Position.y, newPrefab.Position.z + newPrefab.Size.z / 2f);
ClearedPrefabs.Add(newPrefab);
int clearedPrefabs = GetTotalClearedPrefabCount(biome);
int totalPrefabs = RebirthUtilities.GetTotalSpawnedPrefab(biome);
//Log.Out($"ScenarioManagerRebirth-AddPrefab biome: {biome} / clearedPrefabs: {clearedPrefabs} of {totalPrefabs}");
SaveScenario("purge"); // Automatically save after adding
// remove prefab from discovered
RemoveDiscoveredPrefab(name, position, vector);
RemoveDynamicPrefab(name, position);
//Debug.Log($"Prefab: {newPrefab.Name} / position: {newPrefab.Position} / size: {newPrefab.Size} / Difficulty: {newPrefab.Difficulty} / Entities Cleared: {newPrefab.EntitiesCleared} / Reported By: {players} / Biome: {newPrefab.Biome}");
bool reportLocal = false;
string report = string.Format(Localization.Get("PurgePurgedReport"), GetFirstPlayerName(newPrefab), entitiesCleared, Localization.Get(name), Localization.Get("biome_" + biome));
string sound = "purge_discovered";
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsSinglePlayer)
{
reportLocal = true;
RebirthVariables.purgeDisplayPercentage = ((float)clearedPrefabs / totalPrefabs) * 100;
int numPrefabs = clearedPrefabs;
if (clearedPrefabs > totalPrefabs)
{
numPrefabs = totalPrefabs;
}
RebirthVariables.purgeLabel = numPrefabs + "/" + totalPrefabs;
}
else
{
if (!GameManager.IsDedicatedServer)
{
reportLocal = true;
RebirthVariables.purgeDisplayPercentage = ((float)clearedPrefabs / totalPrefabs) * 100;
int numPrefabs = clearedPrefabs;
if (clearedPrefabs > totalPrefabs)
{
numPrefabs = totalPrefabs;
}
RebirthVariables.purgeLabel = numPrefabs + "/" + totalPrefabs;
}
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageRegisterPrefabNavIcon>().Setup("purge_waypoint", vector.x, vector.y, vector.z, report, sound));
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageUpdatePurgeDisplay>().Setup(name, position.x, position.y, position.z, 0, 0, 0, 0, 0, 0, 0), false);
}
if (reportLocal)
{
NavObject navPurged = NavObjectManager.Instance.RegisterNavObject("purge_waypoint", vector, "purge_waypoint");
if (navPurged != null)
{
navPurged.trackedPosition = vector;
}
EntityPlayerLocal primaryPlayer = GameManager.Instance.World.GetPrimaryPlayer();
if (primaryPlayer != null)
{
if (sound != "")
{
Manager.PlayInsidePlayerHead(sound);
}
//Log.Out("ScenarioManagerRebirth-AddPrefab report: " + report);
GameManager.ShowTooltip(primaryPlayer, report, string.Empty);
}
}
}
public static void AddDiscoveredPrefab(string name, Vector3 position, Vector3 size, int difficulty, int entitiesCleared, Dictionary<int, string> players, string biome)
{
//Log.Out("ScenarioManagerRebirth-AddDiscoveredPrefab START");
PrefabInfo newPrefab = new PrefabInfo
{
Name = name,
Position = position,
Size = size,
Difficulty = difficulty,
EntitiesCleared = entitiesCleared,
Players = players,
Biome = biome
};
//Log.Out($"Prefab: {newPrefab.Name} / position: {newPrefab.Position} / size: {newPrefab.Size} / Difficulty: {newPrefab.Difficulty} / Entities Cleared: {newPrefab.EntitiesCleared} / Reported By: {players} / Biome: {newPrefab.Biome}");
if (IsPrefabDiscovered(name, position))
{
//Log.Out("ScenarioManagerRebirth-AddDiscoveredPrefab ALREADY DISCOVERED");
return;
}
DiscoveredPrefabs.Add(newPrefab);
SaveDiscovered();
Vector3 vector = new Vector3(newPrefab.Position.x + newPrefab.Size.x / 2f, newPrefab.Position.y, newPrefab.Position.z + newPrefab.Size.z / 2f);
bool reportLocal = false;
string report = string.Format(Localization.Get("PurgeDiscoveryReport"), GetFirstPlayerName(newPrefab), Localization.Get(name), Localization.Get("biome_" + biome));
string sound = "purge_cleared";
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsSinglePlayer)
{
reportLocal = true;
}
else
{
if (!GameManager.IsDedicatedServer)
{
reportLocal = true;
}
if (players.ContainsKey(-1))
{
report = "";
}
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageScenarioAddDiscoveredPrefab>().Setup("discovered_waypoint_" + difficulty, vector.x, vector.y, vector.z, report, sound));
}
if (reportLocal)
{
//Log.Out("ScenarioManagerRebirth-AddDiscoveredPrefab navobject: " + "discovered_waypoint_" + difficulty);
//Log.Out("ScenarioManagerRebirth-AddDiscoveredPrefab vector: " + vector);
NavObject navDiscovered = NavObjectManager.Instance.RegisterNavObject("discovered_waypoint_" + difficulty, vector, "discovered_waypoint_" + difficulty);
if (navDiscovered != null)
{
navDiscovered.trackedPosition = vector;
}
if (!players.ContainsKey(-1))
{
EntityPlayerLocal primaryPlayer = GameManager.Instance.World.GetPrimaryPlayer();
if (primaryPlayer != null)
{
if (sound != "")
{
Manager.PlayInsidePlayerHead(sound);
}
//Log.Out("ScenarioManagerRebirth-AddDiscoveredPrefab report: " + report);
GameManager.ShowTooltip(primaryPlayer, report, string.Empty);
}
}
}
}
// Check if a prefab is cleared by its name and position
public static bool IsPrefabCleared(string name, Vector3 position)
{
return ClearedPrefabs.Any(p => p.Name == name && p.Position == position);
}
public static bool IsPrefabDiscovered(string name, Vector3 position)
{
return DiscoveredPrefabs.Any(p => p.Name == name && p.Position == position && p.Difficulty != -1);
}
// Remove a prefab from the cleared list
public static void RemovePrefab(string name, Vector3 position)
{
var prefabToRemove = ClearedPrefabs.FirstOrDefault(p => p.Name == name && p.Position == position);
if (prefabToRemove != null)
{
ClearedPrefabs.Remove(prefabToRemove);
SaveScenario("purge");
}
else
{
Debug.LogWarning("Prefab not found.");
}
}
public static void UpdateDiscoveredPrefab(string name, Vector3 position, int entitiesCleared)
{
var prefab = DiscoveredPrefabs.FirstOrDefault(p => p.Name == name && p.Position == position);
// If the prefab is found, update the EntitiesCleared value
if (prefab != null)
{
prefab.EntitiesCleared = entitiesCleared;
}
}
public static int GetDiscoveredPrefabEntitiesCleared(string name, Vector3 position)
{
// Find the prefab in the list that matches the name and position
var prefab = DiscoveredPrefabs.FirstOrDefault(p => p.Name == name && p.Position == position);
// Return the EntitiesCleared value if the prefab is found, otherwise return a default value
return prefab != null ? prefab.EntitiesCleared : -1; // Return -1 if not found
}
public static void RemoveDiscoveredPrefab(string name, Vector3 position, Vector3 location)
{
//Log.Out("ScenarioManagerRebirth-RemoveDiscoveredPrefab START");
var prefabToRemove = DiscoveredPrefabs.FirstOrDefault(p => p.Name == name && p.Position == position);
if (prefabToRemove != null)
{
//Log.Out("ScenarioManagerRebirth-RemoveDiscoveredPrefab 1");
DiscoveredPrefabs.Remove(prefabToRemove);
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsSinglePlayer)
{
//Log.Out("ScenarioManagerRebirth-RemoveDiscoveredPrefab UNREGISTER LOCAL NAV OBJECT: " + "discovered_waypoint_" + prefabToRemove.Difficulty);
//Log.Out("ScenarioManagerRebirth-RemoveDiscoveredPrefab position: " + position);
//Log.Out("ScenarioManagerRebirth-RemoveDiscoveredPrefab location: " + location);
NavObjectManager.Instance.UnRegisterNavObjectByPosition(location, "discovered_waypoint_" + prefabToRemove.Difficulty);
}
else
{
if (!GameManager.IsDedicatedServer)
{
NavObjectManager.Instance.UnRegisterNavObjectByPosition(location, "discovered_waypoint_" + prefabToRemove.Difficulty);
}
//Log.Out("ScenarioManagerRebirth-RemoveDiscoveredPrefab SEND UNREGISTER TO CLIENTS");
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage((NetPackage)NetPackageManager.GetPackage<NetPackageUnregisterNavObject>().Setup("discovered_waypoint_" + prefabToRemove.Difficulty, location.x, location.y, location.z), false);
}
SaveDiscovered();
}
else
{
Debug.LogWarning("Prefab not found.");
}
}
// Retrieve prefabs by player name
public static List<PrefabInfo> GetPrefabsByPlayer(string playerName)
{
return ClearedPrefabs.Where(p => p.PlayerName == playerName).ToList();
}
// Retrieve prefabs by name
public static List<PrefabInfo> GetPrefabsByName(string prefabName)
{
return ClearedPrefabs.Where(p => p.Name == prefabName).ToList();
}
// Retrieve prefabs by position
public static List<PrefabInfo> GetPrefabsByPosition(Vector3 position)
{
return ClearedPrefabs.Where(p => p.Position == position).ToList();
}
// Retrieve prefabs by difficulty
public static List<PrefabInfo> GetPrefabsByDifficulty(int difficulty)
{
return ClearedPrefabs.Where(p => p.Difficulty == difficulty).ToList();
}
// Retrieve prefabs by biome
public static List<PrefabInfo> GetPrefabsByBiome(string biome)
{
return ClearedPrefabs.Where(p => p.Biome == biome).ToList();
}
public static int GetClearedPrefabCount(string biome, int difficulty)
{
return ClearedPrefabs.Count(p => p.Biome == biome && p.Difficulty == difficulty);
}
public static int GetTotalClearedPrefabCount(string biome)
{
return ClearedPrefabs.Count(p => p.Biome == biome);
}
}