Advertisement
Guest User

Untitled

a guest
Mar 11th, 2024
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.01 KB | None | 0 0
  1. using GTA;
  2. using GTA.Native;
  3. using GTA.Math;
  4. using System;
  5. using System.Windows.Forms;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using static SimpleGangWar;
  9.  
  10. public class TierConfig
  11. {
  12. public List<string> Models { get; set; }
  13. public List<string> Weapons { get; set; }
  14. public int Health { get; set; }
  15. public int Armor { get; set; }
  16. public int Accuracy { get; set; }
  17. public CombatMovement CombatMovement { get; set; } // Correctly reference the enum type
  18. public CombatRange CombatRange { get; set; } // Correctly reference the enum type
  19.  
  20. public TierConfig()
  21. {
  22. Models = new List<string>();
  23. Weapons = new List<string>();
  24. }
  25. }
  26. public class SimpleGangWar : Script {
  27. // Settings defined on script variables serve as fallback for settings not defined (or invalid) on .ini config file
  28.  
  29. // Peds: https://github.com/crosire/scripthookvdotnet/blob/d1827497495567d810986aa752f8d903853088fd/source/scripting_v2/GTA.Native/PedHash.cs
  30. // Weapons: https://github.com/crosire/scripthookvdotnet/blob/d1827497495567d810986aa752f8d903853088fd/source/scripting_v2/GTA.Native/WeaponHash.cs
  31. // Peds with images (do not use the exact names listed here): https://wiki.gtanet.work/index.php/Peds - https://docs.fivem.net/docs/game-references/ped-models
  32. private static string[] pedsAllies = { "Families01GFY", "Famca01GMY", "Famdnf01GMY", "Famfor01GMY" };
  33. private static string[] weaponsAllies = { "AssaultRifle", "CompactRifle", "SNSPistol", "VintagePistol", "Pistol", "MicroSMG" };
  34. private static string[] pedsEnemies = { "BallaEast01GMY", "BallaOrig01GMY", "Ballas01GFY", "BallaSout01GMY" };
  35. private static string[] weaponsEnemies = { "MicroSMG", "MachinePistol", "Gusenberg", "Musket", "Pistol", "VintagePistol", "CompactRifle" };
  36. private static readonly char[] StringSeparators = { ',', ';' };
  37. Dictionary<string, TierConfig> alliedTiers = new Dictionary<string, TierConfig>();
  38. Dictionary<string, TierConfig> enemyTiers = new Dictionary<string, TierConfig>();
  39.  
  40.  
  41. private static int healthAllies = 120;
  42. private static int armorAllies = 0;
  43. private static int healthEnemies = 120;
  44. private static int armorEnemies = 0;
  45. private static int accuracyAllies = 5;
  46. private static int accuracyEnemies = 5;
  47. private static CombatMovement combatMovementAllies = CombatMovement.Offensive;
  48. private static CombatMovement combatMovementEnemies = CombatMovement.Offensive;
  49. private static CombatRange combatRangeAllies = CombatRange.Far;
  50. private static CombatRange combatRangeEnemies = CombatRange.Far;
  51.  
  52. private static int maxPedsPerTeam = 10;
  53. private static Keys hotkey = Keys.B;
  54. private static Keys spawnHotkey = Keys.N;
  55. private static bool noWantedLevel = true;
  56. private static bool showBlipsOnPeds = true;
  57. private static bool dropWeaponOnDead = false;
  58. private static bool removeDeadPeds = true;
  59. private static bool runToSpawnpoint = true;
  60. private static bool processOtherRelationshipGroups = false;
  61. private static bool neutralPlayer = false;
  62. private static int spawnpointFloodLimitPeds = 10;
  63. private static float spawnpointFloodLimitDistance = 8.0f;
  64. private static int idleInterval = 500;
  65. private static int battleInterval = 100;
  66. private static int maxPedsAllies;
  67. private static int maxPedsEnemies;
  68. private static int maxSpawnPedsAllies = -1;
  69. private static int maxSpawnPedsEnemies = -1;
  70.  
  71. // From here, internal script variables - do not change!
  72.  
  73. private int relationshipGroupAllies;
  74. private int relationshipGroupEnemies;
  75. private int originalWantedLevel;
  76.  
  77. private int spawnedAlliesCounter;
  78. private int spawnedEnemiesCounter;
  79.  
  80. private List<Ped> spawnedAllies = new List<Ped>();
  81. private List<Ped> spawnedEnemies = new List<Ped>();
  82. private List<Ped> deadPeds = new List<Ped>();
  83. private List<Ped> pedsRemove = new List<Ped>();
  84. private List<int> processedRelationshipGroups = new List<int>();
  85.  
  86. private bool spawnEnabled = true;
  87. private Stage stage = Stage.Initial;
  88.  
  89. private Vector3 spawnpointAllies;
  90. private Vector3 spawnpointEnemies;
  91. private float spawnpointsDistance;
  92.  
  93. private Blip spawnpointBlipAllies;
  94. private Blip spawnpointBlipEnemies;
  95.  
  96. private static Relationship[] allyRelationships = { Relationship.Companion, Relationship.Like, Relationship.Respect };
  97. private static Relationship[] enemyRelationships = { Relationship.Hate, Relationship.Dislike };
  98.  
  99. private int relationshipGroupPlayer;
  100. private static Random random;
  101.  
  102. public enum CombatMovement {
  103. // https://runtime.fivem.net/doc/natives/?_0x4D9CA1009AFBD057
  104. // NOTE Stationary, Suicidal - do not seem to work as expected
  105. Stationary = 0,
  106. Defensive = 1,
  107. Offensive = 2,
  108. Suicidal = 3,
  109. Disabled = 0,
  110. Random = -1
  111. }
  112. private static CombatMovement[] randomizableCombatMovements = { CombatMovement.Defensive, CombatMovement.Offensive };
  113.  
  114. public enum CombatRange {
  115. // https://docs.fivem.net/natives/?_0x3C606747B23E497B
  116. Near = 0,
  117. Medium = 1,
  118. Far = 2,
  119. VeryFar= 3,
  120. Disabled = 0,
  121. Random = -1
  122. }
  123. private static CombatRange[] randomizableCombatRanges = { CombatRange.Near, CombatRange.Medium, CombatRange.Far, CombatRange.VeryFar };
  124.  
  125. private enum Stage {
  126. Initial = 0,
  127. DefiningEnemySpawnpoint = 1,
  128. EnemySpawnpointDefined = 2,
  129. Running = 3,
  130. StopKeyPressed = 4
  131. }
  132.  
  133. private class SettingsHeader {
  134. public static readonly string Allies = "ALLIED_TEAM";
  135. public static readonly string Enemies = "ENEMY_TEAM";
  136. public static readonly string General = "SETTINGS";
  137. }
  138.  
  139.  
  140. public SimpleGangWar() {
  141. Tick += MainLoop;
  142. KeyUp += OnKeyUp;
  143. Interval = idleInterval;
  144.  
  145. ScriptSettings config = ScriptSettings.Load("scripts\\SimpleGangWar.ini");
  146. string configString;
  147.  
  148. healthAllies = config.GetValue(SettingsHeader.Allies, "Health", healthAllies);
  149. healthEnemies = config.GetValue(SettingsHeader.Enemies, "Health", healthEnemies);
  150.  
  151. armorAllies = config.GetValue(SettingsHeader.Allies, "Armor", armorAllies);
  152. armorEnemies = config.GetValue(SettingsHeader.Enemies, "Armor", armorEnemies);
  153.  
  154. accuracyAllies = config.GetValue(SettingsHeader.Allies, "Accuracy", accuracyAllies);
  155. accuracyEnemies = config.GetValue(SettingsHeader.Enemies, "Accuracy", accuracyEnemies);
  156.  
  157. configString = config.GetValue<string>(SettingsHeader.Allies, "CombatMovement", "");
  158. combatMovementAllies = EnumParse(configString, combatMovementAllies);
  159. configString = config.GetValue<string>(SettingsHeader.Enemies, "CombatMovement", "");
  160. combatMovementEnemies = EnumParse(configString, combatMovementEnemies);
  161.  
  162. configString = config.GetValue<string>(SettingsHeader.Allies, "CombatRange", "");
  163. combatRangeAllies = EnumParse(configString, combatRangeAllies);
  164. configString = config.GetValue<string>(SettingsHeader.Enemies, "CombatRange", "");
  165. combatRangeEnemies = EnumParse(configString, combatRangeEnemies);
  166.  
  167. configString = config.GetValue<string>(SettingsHeader.Allies, "Weapons", "");
  168. weaponsAllies = ArrayParse(configString, weaponsAllies);
  169. configString = config.GetValue<string>(SettingsHeader.Enemies, "Weapons", "");
  170. weaponsEnemies = ArrayParse(configString, weaponsEnemies);
  171.  
  172. configString = config.GetValue<string>(SettingsHeader.Allies, "Models", "");
  173. pedsAllies = ArrayParse(configString, pedsAllies);
  174. configString = config.GetValue<string>(SettingsHeader.Enemies, "Models", "");
  175. pedsEnemies = ArrayParse(configString, pedsEnemies);
  176.  
  177. configString = config.GetValue<string>(SettingsHeader.General, "Hotkey", "");
  178. hotkey = EnumParse(configString, hotkey);
  179. configString = config.GetValue<string>(SettingsHeader.General, "SpawnHotkey", "");
  180. spawnHotkey = EnumParse(configString, spawnHotkey);
  181.  
  182. maxPedsPerTeam = config.GetValue(SettingsHeader.General, "MaxPedsPerTeam", maxPedsPerTeam);
  183. noWantedLevel = config.GetValue(SettingsHeader.General, "NoWantedLevel", noWantedLevel);
  184. showBlipsOnPeds = config.GetValue(SettingsHeader.General, "ShowBlipsOnPeds", showBlipsOnPeds);
  185. dropWeaponOnDead = config.GetValue(SettingsHeader.General, "DropWeaponOnDead", dropWeaponOnDead);
  186. removeDeadPeds = config.GetValue(SettingsHeader.General, "RemoveDeadPeds", removeDeadPeds);
  187. runToSpawnpoint = config.GetValue(SettingsHeader.General, "RunToSpawnpoint", runToSpawnpoint);
  188. processOtherRelationshipGroups = config.GetValue(SettingsHeader.General, "ProcessOtherRelationshipGroups", processOtherRelationshipGroups);
  189. neutralPlayer = config.GetValue(SettingsHeader.General, "NeutralPlayer", neutralPlayer);
  190. spawnpointFloodLimitPeds = config.GetValue(SettingsHeader.General, "SpawnpointFloodLimitPeds", spawnpointFloodLimitPeds);
  191. spawnpointFloodLimitDistance = config.GetValue(SettingsHeader.General, "SpawnpointFloodLimitDistance", spawnpointFloodLimitDistance);
  192. idleInterval = config.GetValue(SettingsHeader.General, "IdleInterval", idleInterval);
  193. battleInterval = config.GetValue(SettingsHeader.General, "BattleInterval", battleInterval);
  194.  
  195. maxPedsAllies = config.GetValue(SettingsHeader.Allies, "MaxPeds", maxPedsPerTeam);
  196. maxPedsEnemies = config.GetValue(SettingsHeader.Enemies, "MaxPeds", maxPedsPerTeam);
  197. maxSpawnPedsAllies = config.GetValue(SettingsHeader.Allies, "MaxSpawnPeds", maxSpawnPedsAllies);
  198. maxSpawnPedsEnemies = config.GetValue(SettingsHeader.Enemies, "MaxSpawnPeds", maxSpawnPedsEnemies);
  199.  
  200. relationshipGroupAllies = World.AddRelationshipGroup("simplegangwar_allies");
  201. relationshipGroupEnemies = World.AddRelationshipGroup("simplegangwar_enemies");
  202. relationshipGroupPlayer = Game.Player.Character.RelationshipGroup;
  203. SetRelationshipBetweenGroups(Relationship.Hate, relationshipGroupAllies, relationshipGroupEnemies);
  204. SetRelationshipBetweenGroups(Relationship.Respect, relationshipGroupAllies, relationshipGroupAllies);
  205. SetRelationshipBetweenGroups(Relationship.Respect, relationshipGroupEnemies, relationshipGroupEnemies);
  206. SetRelationshipBetweenGroups(Relationship.Respect, relationshipGroupAllies, relationshipGroupPlayer);
  207. if (!neutralPlayer) {
  208. SetRelationshipBetweenGroups(Relationship.Hate, relationshipGroupEnemies, relationshipGroupPlayer);
  209. } else {
  210. SetRelationshipBetweenGroups(Relationship.Respect, relationshipGroupEnemies, relationshipGroupPlayer);
  211. }
  212. // TODO processedRelationshipGroups not being used?
  213. processedRelationshipGroups.Add(relationshipGroupPlayer);
  214. processedRelationshipGroups.Add(relationshipGroupAllies);
  215. processedRelationshipGroups.Add(relationshipGroupEnemies);
  216.  
  217. random = new Random();
  218. LoadTierConfigs();
  219. SetupTierProbabilities();
  220.  
  221. UI.Notify("SimpleGangWar loaded");
  222. }
  223.  
  224.  
  225. /// <summary>
  226. /// The main script loop runs at the frequency delimited by the Interval, which varies depending if the battle is running or not.
  227. /// The loop only spawn peds and processes them as the battle is running. Any other actions that happen outside a battle are processed by Key event handlers.
  228. /// </summary>
  229. private void MainLoop(object sender, EventArgs e) {
  230. if (stage >= Stage.Running) {
  231. try {
  232. SpawnPeds(true);
  233. SpawnPeds(false);
  234.  
  235. SetUnmanagedPedsInRelationshipGroups();
  236. ProcessSpawnedPeds(true);
  237. ProcessSpawnedPeds(false);
  238. } catch (FormatException exception) {
  239. UI.ShowSubtitle("(SimpleGangWar) Error! " + exception.Message);
  240. }
  241. }
  242. }
  243.  
  244.  
  245. /// <summary>
  246. /// Key event handler for key releases.
  247. /// </summary>
  248. private void OnKeyUp(object sender, KeyEventArgs e) {
  249. if (e.KeyCode == hotkey) {
  250. switch (stage) {
  251. case Stage.Initial:
  252. UI.ShowHelpMessage("Welcome to SimpleGangWar!\nGo to the enemy spawnpoint and press the hotkey again to define it.", 180000, true);
  253. stage = Stage.DefiningEnemySpawnpoint;
  254. break;
  255. case Stage.DefiningEnemySpawnpoint:
  256. DefineSpawnpoint(false);
  257. UI.ShowHelpMessage("Enemy spawnpoint defined! Now go to the allied spawnpoint and press the hotkey again to define it.", 180000, true);
  258. stage = Stage.EnemySpawnpointDefined;
  259. break;
  260. case Stage.EnemySpawnpointDefined:
  261. DefineSpawnpoint(true);
  262. SetupBattle();
  263. UI.ShowHelpMessage("The battle begins NOW!", 5000, true);
  264. stage = Stage.Running;
  265. break;
  266. case Stage.Running:
  267. UI.ShowHelpMessage("Do you really want to stop the battle? Press the hotkey again to confirm.", 7000, true);
  268. stage = Stage.StopKeyPressed;
  269. break;
  270. case Stage.StopKeyPressed:
  271. UI.ShowHelpMessage("The battle has ended!", 5000, true);
  272. stage = Stage.Initial;
  273. Teardown();
  274. break;
  275. }
  276. } else if (e.KeyCode == spawnHotkey) {
  277. spawnEnabled = !spawnEnabled;
  278. BlinkSpawnpoint(true);
  279. BlinkSpawnpoint(false);
  280. }
  281. }
  282.  
  283.  
  284. /// <summary>
  285. /// After the spawnpoints are defined, some tweaks are required just before the battle begins.
  286. /// </summary>
  287. private void SetupBattle() {
  288. Interval = battleInterval;
  289. spawnpointsDistance = spawnpointEnemies.DistanceTo(spawnpointAllies);
  290. spawnedAlliesCounter = 0;
  291. spawnedEnemiesCounter = 0;
  292.  
  293. if (noWantedLevel) {
  294. originalWantedLevel = Game.MaxWantedLevel;
  295. Game.MaxWantedLevel = 0;
  296. }
  297. }
  298.  
  299. /// <summary>
  300. /// Spawn peds on the given team, until the ped limit for that team is reached.
  301. /// </summary>
  302. /// <param name="alliedTeam">true=ally team / false=enemy team</param>
  303. private void SpawnPeds(bool alliedTeam) {
  304. while (spawnEnabled && CanPedsSpawn(alliedTeam)) {
  305. SpawnRandomPed(alliedTeam);
  306. }
  307. }
  308.  
  309. /// <summary>
  310. /// Determine if peds on the given team should spawn or not.
  311. /// </summary>
  312. /// <param name="alliedTeam">true=ally team / false=enemy team</param>
  313. private bool CanPedsSpawn(bool alliedTeam) {
  314. List<Ped> spawnedPedsList = alliedTeam ? spawnedAllies : spawnedEnemies;
  315. int maxPeds = alliedTeam ? maxPedsAllies : maxPedsEnemies;
  316. int maxSpawnPeds = alliedTeam ? maxSpawnPedsAllies : maxSpawnPedsEnemies;
  317. int totalSpawnedPeds = alliedTeam ? spawnedAlliesCounter : spawnedEnemiesCounter;
  318.  
  319. // by MaxPeds in the team
  320. if (spawnedPedsList.Count >= maxPeds) return false;
  321.  
  322. // by MaxSpawnPeds limit
  323. if (maxSpawnPeds >= 0 && totalSpawnedPeds > maxSpawnPeds) return false;
  324.  
  325. // by SpawnpointFlood limit
  326. if (spawnpointFloodLimitPeds < 1) return true;
  327.  
  328. Vector3 spawnpointPosition = alliedTeam ? spawnpointAllies : spawnpointEnemies;
  329. Ped[] pedsNearSpawnpoint = World.GetNearbyPeds(spawnpointPosition, spawnpointFloodLimitDistance);
  330.  
  331. int pedsNearSpawnpointCount = 0;
  332. foreach (Ped ped in pedsNearSpawnpoint) {
  333. if (ped.IsAlive && spawnedPedsList.Contains(ped)) pedsNearSpawnpointCount++;
  334. }
  335.  
  336. return pedsNearSpawnpointCount < spawnpointFloodLimitPeds;
  337. }
  338.  
  339. void LoadTierConfigs()
  340. {
  341. var config = ScriptSettings.Load("scripts\\SimpleGangWar.ini");
  342.  
  343. // Define tiers
  344. string[] tiers = { "GRUNT", "ELITE", "SNIPER", "JUGGERNAUT", "MELEE" };
  345.  
  346. // Load configurations for each tier
  347. foreach (var tier in tiers)
  348. {
  349. alliedTiers[tier] = LoadTierConfig(config, "ALLIED_TEAM_" + tier);
  350. enemyTiers[tier] = LoadTierConfig(config, "ENEMY_TEAM_" + tier);
  351. }
  352. }
  353.  
  354. TierConfig LoadTierConfig(ScriptSettings config, string section)
  355. {
  356. TierConfig tierConfig = new TierConfig();
  357.  
  358. // Splitting Models and Weapons strings by commas and trimming spaces
  359. tierConfig.Models = config.GetValue<string>(section, "Models", "").Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(m => m.Trim()).ToList();
  360. tierConfig.Weapons = config.GetValue<string>(section, "Weapons", "").Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(w => w.Trim()).ToList();
  361.  
  362. // Reading other properties directly
  363. tierConfig.Health = config.GetValue<int>(section, "Health", 100);
  364. tierConfig.Armor = config.GetValue<int>(section, "Armor", 0);
  365. tierConfig.Accuracy = config.GetValue<int>(section, "Accuracy", 10);
  366.  
  367. // Handling enum values with parsing
  368. string combatMovementStr = config.GetValue<string>(section, "CombatMovement", "Stationary");
  369. CombatMovement combatMovement;
  370. Enum.TryParse(combatMovementStr, out combatMovement);
  371. tierConfig.CombatMovement = combatMovement;
  372.  
  373. string combatRangeStr = config.GetValue<string>(section, "CombatRange", "Medium");
  374. CombatRange combatRange;
  375. Enum.TryParse(combatRangeStr, out combatRange);
  376. tierConfig.CombatRange = combatRange;
  377.  
  378. return tierConfig;
  379. }
  380.  
  381. public class TierConfig
  382. {
  383. public List<string> Models { get; set; }
  384. public List<string> Weapons { get; set; }
  385. public int Health { get; set; }
  386. public int Armor { get; set; }
  387. public int Accuracy { get; set; }
  388. public CombatMovement CombatMovement { get; set; }
  389. public CombatRange CombatRange { get; set; }
  390. public double Probability { get; set; } // Add this line
  391.  
  392. public TierConfig()
  393. {
  394. Models = new List<string>();
  395. Weapons = new List<string>();
  396. }
  397. }
  398.  
  399. void SetupTierProbabilities()
  400. {
  401. // Assuming alliedTiers and enemyTiers have already been populated with TierConfig instances
  402.  
  403. // Set probabilities for allied tiers
  404. alliedTiers["GRUNT"].Probability = 0.5;
  405. alliedTiers["ELITE"].Probability = 0.15;
  406. alliedTiers["SNIPER"].Probability = 0.15;
  407. alliedTiers["MELEE"].Probability = 0.15;
  408. alliedTiers["JUGGERNAUT"].Probability = 0.05;
  409.  
  410. // Set probabilities for enemy tiers
  411. enemyTiers["GRUNT"].Probability = 0.5;
  412. enemyTiers["ELITE"].Probability = 0.15;
  413. enemyTiers["SNIPER"].Probability = 0.15;
  414. enemyTiers["MELEE"].Probability = 0.15;
  415. enemyTiers["JUGGERNAUT"].Probability = 0.05;
  416.  
  417. // Note: Make sure the probabilities for each tier collection sum up to 1.0
  418. }
  419.  
  420. /// <summary>
  421. /// Spawns a ped on the given team, ready to fight.
  422. /// </summary>
  423. /// <param name="alliedTeam">true=ally team / false=enemy team</param>
  424. /// <returns>The spawned ped</returns>
  425. private Ped SpawnRandomPed(bool alliedTeam)
  426. {
  427. string selectedTier = SelectTierBasedOnProbability(alliedTeam ? alliedTiers : enemyTiers);
  428.  
  429. TierConfig config = alliedTeam ? alliedTiers[selectedTier] : enemyTiers[selectedTier];
  430.  
  431. string pedModelName = RandomChoice(config.Models.ToArray());
  432. string weaponName = RandomChoice(config.Weapons.ToArray());
  433.  
  434. Model pedModel = new Model(pedModelName);
  435. WeaponHash weaponHash;
  436. if (!Enum.TryParse(weaponName, true, out weaponHash))
  437. {
  438. UI.Notify($"Weapon name {weaponName} does not exist!");
  439. return null;
  440. }
  441.  
  442. pedModel.Request(500);
  443. if (!pedModel.IsLoaded)
  444. {
  445. UI.Notify($"Model {pedModelName} could not be loaded.");
  446. return null;
  447. }
  448.  
  449. Vector3 pedPosition = alliedTeam ? spawnpointAllies : spawnpointEnemies;
  450. Ped ped = World.CreatePed(pedModel, pedPosition);
  451. if (ped == null)
  452. {
  453. UI.Notify("Failed to create ped.");
  454. return null;
  455. }
  456.  
  457. ped.Weapons.Give(weaponHash, 1, true, true);
  458. ped.Health = config.Health;
  459. ped.Armor = config.Armor;
  460. ped.Accuracy = config.Accuracy;
  461. ped.RelationshipGroup = alliedTeam ? relationshipGroupAllies : relationshipGroupEnemies;
  462. ped.DropsWeaponsOnDeath = dropWeaponOnDead;
  463.  
  464. TierConfig Tierconfig = alliedTeam ? alliedTiers[selectedTier] : enemyTiers[selectedTier];
  465.  
  466. if (Tierconfig.CombatMovement != CombatMovement.Disabled)
  467. {
  468. Function.Call(Hash.SET_PED_COMBAT_MOVEMENT, ped, (int)config.CombatMovement);
  469. }
  470. if (Tierconfig.CombatRange != CombatRange.Disabled)
  471. {
  472. Function.Call(Hash.SET_PED_COMBAT_RANGE, ped, (int)config.CombatRange);
  473. }
  474.  
  475. Function.Call(Hash.SET_PED_COMBAT_ATTRIBUTES, ped, 46, true); // Force peds to fight
  476. Function.Call(Hash.SET_PED_SEEING_RANGE, ped, spawnpointsDistance);
  477.  
  478. if (showBlipsOnPeds) {
  479. Blip blip = ped.AddBlip();
  480. blip.Color = alliedTeam ? BlipColor.Blue : BlipColor.Orange;
  481. blip.Name = alliedTeam ? "Ally team member" : "Enemy team member";
  482. blip.Scale = 0.5f;
  483. }
  484.  
  485. ped.Task.ClearAllImmediately();
  486. ped.AlwaysKeepTask = true; // TODO Investigate if this could be making peds avoid reloads
  487.  
  488. if (alliedTeam) {
  489. spawnedAllies.Add(ped);
  490. spawnedAlliesCounter++;
  491. } else {
  492. spawnedEnemies.Add(ped);
  493. spawnedEnemiesCounter++;
  494. }
  495.  
  496. pedModel.MarkAsNoLongerNeeded(); // Release the model for memory management
  497. return ped;
  498. }
  499.  
  500. private string SelectTierBasedOnProbability(Dictionary<string, TierConfig> tierConfigs)
  501. {
  502. double randomPoint = random.NextDouble();
  503. double cumulativeProbability = 0.0;
  504.  
  505. foreach (KeyValuePair<string, TierConfig> entry in tierConfigs)
  506. {
  507. cumulativeProbability += entry.Value.Probability;
  508. if (randomPoint <= cumulativeProbability)
  509. {
  510. return entry.Key;
  511. }
  512. }
  513.  
  514. return "GRUNT"; // Default fallback if probabilities do not sum to 1 or in case of error
  515. }
  516.  
  517. /// <summary>
  518. /// Processes the spawned peds of the given team. This includes making sure they fight and process their removal as they are killed in action.
  519. /// </summary>
  520. /// <param name="alliedTeam">true=ally team / false=enemy team</param>
  521. private void ProcessSpawnedPeds(bool alliedTeam) {
  522. List<Ped> pedList = alliedTeam ? spawnedAllies : spawnedEnemies;
  523.  
  524. foreach (Ped ped in pedList) {
  525. if (ped.IsDead) {
  526. ped.CurrentBlip.Remove();
  527. pedsRemove.Add(ped);
  528. deadPeds.Add(ped);
  529. if (removeDeadPeds) ped.MarkAsNoLongerNeeded();
  530. } else if (ped.IsIdle && !ped.IsRunning) {
  531. if (runToSpawnpoint) ped.Task.RunTo(alliedTeam ? spawnpointEnemies : spawnpointAllies);
  532. else ped.Task.FightAgainstHatedTargets(spawnpointsDistance);
  533. }
  534. }
  535.  
  536. foreach (Ped ped in pedsRemove) {
  537. pedList.Remove(ped);
  538. }
  539.  
  540. pedsRemove.Clear();
  541. }
  542.  
  543. /// <summary>
  544. /// Set the spawnpoint for the given team on the position where the player is at.
  545. /// </summary>
  546. /// <param name="alliedTeam">true=ally team / false=enemy team</param>
  547. private void DefineSpawnpoint(bool alliedTeam) {
  548. Vector3 position = Game.Player.Character.Position;
  549. Blip blip = World.CreateBlip(position);
  550.  
  551. if (alliedTeam) {
  552. spawnpointAllies = position;
  553. spawnpointBlipAllies = blip;
  554. blip.Sprite = BlipSprite.TargetA;
  555. blip.Color = BlipColor.Blue;
  556. blip.Name = "Ally spawnpoint";
  557. } else {
  558. spawnpointEnemies = position;
  559. spawnpointBlipEnemies = blip;
  560. blip.Sprite = BlipSprite.TargetE;
  561. blip.Color = BlipColor.Orange;
  562. blip.Name = "Enemy spawnpoint";
  563. }
  564.  
  565. BlinkSpawnpoint(alliedTeam);
  566. }
  567.  
  568. /// <summary>
  569. /// Blink or stop blinking the spawnpoint blip of the given team, depending on if the spawn is disabled (blink) or not (stop blinking).
  570. /// </summary>
  571. /// <param name="alliedTeam">true=ally team / false=enemy team</param>
  572. private void BlinkSpawnpoint(bool alliedTeam) {
  573. Blip blip = alliedTeam ? spawnpointBlipAllies : spawnpointBlipEnemies;
  574. if (blip != null) blip.IsFlashing = !spawnEnabled;
  575. }
  576.  
  577. /// <summary>
  578. /// Get all the relationship groups from foreign peds (those that are not part of SimpleGangWar), and set the relationship between these groups and the SimpleGangWar groups.
  579. /// </summary>
  580. private void SetUnmanagedPedsInRelationshipGroups() {
  581. if (processOtherRelationshipGroups) {
  582. foreach (Ped ped in World.GetAllPeds()) {
  583. if (ped.IsHuman && !ped.IsPlayer) {
  584. Relationship pedRelationshipWithPlayer = ped.GetRelationshipWithPed(Game.Player.Character);
  585. int relationshipGroup = ped.RelationshipGroup;
  586.  
  587. if (relationshipGroup != relationshipGroupAllies && relationshipGroup != relationshipGroupEnemies && relationshipGroup != relationshipGroupPlayer) {
  588. if (allyRelationships.Contains(pedRelationshipWithPlayer)) {
  589. SetRelationshipBetweenGroups(Relationship.Respect, relationshipGroup, relationshipGroupAllies);
  590. SetRelationshipBetweenGroups(Relationship.Hate, relationshipGroup, relationshipGroupEnemies);
  591. } else if (enemyRelationships.Contains(pedRelationshipWithPlayer)) {
  592. SetRelationshipBetweenGroups(Relationship.Respect, relationshipGroup, relationshipGroupEnemies);
  593. SetRelationshipBetweenGroups(Relationship.Hate, relationshipGroup, relationshipGroupAllies);
  594. }
  595. }
  596. }
  597. }
  598. }
  599. }
  600.  
  601. /// <summary>
  602. /// Physically delete the peds from the given list from the game world.
  603. /// </summary>
  604. /// <param name="pedList">List of peds to teardown</param>
  605. private void TeardownPeds(List<Ped> pedList) {
  606. foreach (Ped ped in pedList) {
  607. if (ped.Exists()) ped.Delete();
  608. }
  609. }
  610.  
  611. /// <summary>
  612. /// Manage the battle teardown on user requests. This brings the game to an initial state, before battle start and spawnpoint definition.
  613. /// </summary>
  614. private void Teardown() {
  615. Interval = idleInterval;
  616. spawnpointBlipAllies.Remove();
  617. spawnpointBlipEnemies.Remove();
  618.  
  619. TeardownPeds(spawnedAllies);
  620. TeardownPeds(spawnedEnemies);
  621. TeardownPeds(deadPeds);
  622.  
  623. spawnedAllies.Clear();
  624. spawnedEnemies.Clear();
  625. deadPeds.Clear();
  626. pedsRemove.Clear();
  627. processedRelationshipGroups.Clear();
  628.  
  629. if (noWantedLevel) Game.MaxWantedLevel = originalWantedLevel;
  630. }
  631.  
  632. /// <summary>
  633. /// Set the relationship between two given groups. The relationship is set twice, on both possible combinations.
  634. /// </summary>
  635. /// <param name="relationship">Relationship to set between the groups</param>
  636. /// <param name="groupA">One group</param>
  637. /// <param name="groupB">Other group</param>
  638. private void SetRelationshipBetweenGroups(Relationship relationship, int groupA, int groupB) {
  639. World.SetRelationshipBetweenGroups(relationship, groupA, groupB);
  640. World.SetRelationshipBetweenGroups(relationship, groupB, groupA);
  641. }
  642.  
  643. /// <summary>
  644. /// Choose a random item from a given array, containing objects of type T
  645. /// </summary>
  646. /// <typeparam name="T">Type of objects in the array</typeparam>
  647. /// <param name="array">Array to choose from</param>
  648. /// <returns>A random item from the array</returns>
  649. private T RandomChoice<T>(T[] array)
  650. {
  651. if (array == null || array.Length == 0)
  652. {
  653. throw new InvalidOperationException("Cannot select a random item from an empty array.");
  654. }
  655. return array[random.Next(0, array.Length)];
  656. }
  657.  
  658. /// <summary>
  659. /// Given a string key from an enum, return the referenced enum object.
  660. /// </summary>
  661. /// <typeparam name="EnumType">The whole enum object, to choose an option from</typeparam>
  662. /// <param name="enumKey">The enum key as string</param>
  663. /// <param name="defaultValue">What enum option to return if the referenced enum key does not exist in the enum</param>
  664. /// <returns>The chosen enum option</returns>
  665. private EnumType EnumParse<EnumType>(string enumKey, EnumType defaultValue) where EnumType : struct {
  666. EnumType returnValue;
  667. if (!Enum.TryParse(enumKey, true, out returnValue)) returnValue = defaultValue;
  668. return returnValue;
  669. }
  670.  
  671. /// <summary>
  672. /// Given a string of words to be split, split them and return a string array.
  673. /// </summary>
  674. /// <param name="stringInput">Input string</param>
  675. /// <param name="defaultArray">Array to return if the input string contains no items</param>
  676. /// <returns>A string array</returns>
  677. private string[] ArrayParse(string stringInput, string[] defaultArray) {
  678. string[] resultArray = stringInput.Replace(" ", string.Empty).Split(StringSeparators, StringSplitOptions.RemoveEmptyEntries);
  679. if (resultArray.Length == 0) resultArray = defaultArray;
  680. return resultArray;
  681. }
  682. }
  683.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement