GTA 5 Group Making and Peds Question
-
So, I have this C# script mod that I am making which spawns a couple waves of enemies. I made them not flee when people fire and for them to have both melee and ranged weapons. But, when putting them in a group they still attack each other. I have changed the game config file settings to include more peds that are allowed in one group.
Code below:
I can submit a video of what happens if you guys want or don't understand.using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
using GTA;
using GTA.Math;
using GTA.Native;
using GTA.NaturalMotion;namespace GTA_Mod_Menu
{
public abstract class Wave
{
public Random randomWep = new Random();
public Random randomPed = new Random();public static PedHash[] securityPeds = { PedHash.ChemSec01SMM, PedHash.CiaSec01SMM, PedHash.HighSec03SMM, PedHash.FibSec01, PedHash.FibSec01SMM, PedHash.HighSec04SMM, PedHash.Highsec01SMM, PedHash.Highsec02SMM, PedHash.SecuroGuardMale01, PedHash.WestSec01SMY, PedHash.Security01SMM, PedHash.WestSec02SMY }; public static WeaponHash[] meleeweaponArr = { // melee WeaponHash.SwitchBlade, WeaponHash.Crowbar, WeaponHash.Knife, WeaponHash.Dagger, WeaponHash.Bat, WeaponHash.Bottle, WeaponHash.Wrench, WeaponHash.Unarmed, WeaponHash.Flashlight, WeaponHash.Hammer, WeaponHash.GolfClub, WeaponHash.Hatchet, WeaponHash.StoneHatchet, WeaponHash.KnuckleDuster, WeaponHash.PoolCue, WeaponHash.Nightstick, WeaponHash.BattleAxe, WeaponHash.Pistol, WeaponHash.PumpShotgun, WeaponHash.MiniSMG, WeaponHash.APPistol, WeaponHash.Revolver, WeaponHash.HeavyPistol, WeaponHash.MarksmanPistol, WeaponHash.MachinePistol, WeaponHash.SNSPistol, WeaponHash.CombatPistol, WeaponHash.VintagePistol, WeaponHash.DoubleActionRevolver, WeaponHash.MicroSMG, WeaponHash.SawnOffShotgun, WeaponHash.Pistol, WeaponHash.PumpShotgun, WeaponHash.MiniSMG, WeaponHash.APPistol, WeaponHash.MachinePistol, WeaponHash.SNSPistol, WeaponHash.CombatPistol, WeaponHash.MicroSMG, WeaponHash.SawnOffShotgun, WeaponHash.CeramicPistol, WeaponHash.PericoPistol, WeaponHash.DoubleBarrelShotgun }; public static WeaponHash[] BGWeaponArr = { WeaponHash.SMG, WeaponHash.AssaultRifle, WeaponHash.CarbineRifle, WeaponHash.SniperRifle, WeaponHash.HeavySniper, WeaponHash.MarksmanRifle, WeaponHash.MilitaryRifle, WeaponHash.SpecialCarbine, WeaponHash.AssaultShotgun, WeaponHash.HeavyShotgun, WeaponHash.SweeperShotgun, WeaponHash.CompactRifle, WeaponHash.BullpupRifle, WeaponHash.BullpupShotgun, WeaponHash.AdvancedRifle, WeaponHash.MG }; public abstract void Spawn(); public abstract bool IsDone(); } public class Wave1 : Wave { PedGroup chineseTriad = null; public override void Spawn() { GTA.UI.Notify("Wave 1: Chinese Triad Attacking!"); var First = World.CreatePed(PedHash.ChiCold01GMM, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 50, 0))); int indeX = randomWep.Next(meleeweaponArr.Length); First.Weapons.Give(meleeweaponArr[indeX], 200, true, true); chineseTriad = new PedGroup(); chineseTriad.Add(First, true); for (int i = 0; i < 10; i++) { int index1 = randomWep.Next(meleeweaponArr.Length); var W1Part1 = World.CreatePed(PedHash.ChiCold01GMM, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 50, 0))); var W1Part2 = World.CreatePed(PedHash.ChiGoon01GMM, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 75, 0))); var W1Part3 = World.CreatePed(PedHash.ChiGoon02GMM, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 100, 0))); chineseTriad.Add(W1Part1, false); chineseTriad.Add(W1Part2, false); chineseTriad.Add(W1Part3, false); W1Part1.Weapons.Give(meleeweaponArr[index1], 200, true, true); W1Part1.Health = 200; Function.Call(Hash.SET_PED_COMBAT_ABILITY, W1Part1, 50); Function.Call(Hash.SET_PED_COMBAT_ATTRIBUTES, W1Part1, 46, true); W1Part1.Task.FightAgainst(Game.Player.Character); W1Part2.Weapons.Give(meleeweaponArr[index1], 200, true, true); W1Part2.Health = 200; Function.Call(Hash.SET_PED_COMBAT_ABILITY, W1Part2, 50); Function.Call(Hash.SET_PED_COMBAT_ATTRIBUTES, W1Part2, 46, true); W1Part2.Task.FightAgainst(Game.Player.Character); W1Part3.Weapons.Give(meleeweaponArr[index1], 200, true, true); W1Part3.Health = 200; Function.Call(Hash.SET_PED_COMBAT_ABILITY, W1Part3, 50); Function.Call(Hash.SET_PED_COMBAT_ATTRIBUTES, W1Part3, 46, true); W1Part3.Task.FightAgainst(Game.Player.Character); } } public override bool IsDone() { if (chineseTriad != null) { foreach (Ped ped in chineseTriad.ToList()) { if (!ped.IsDead) { return false; } } GTA.UI.Notify("First wave is dead!"); return true; } return false; } } public class Wave2 : Wave { PedGroup chineseTriad = null; public override void Spawn() { GTA.UI.Notify("Wave 2: Reinforcements Inbound"); var Second = World.CreatePed(PedHash.ChiBoss01GMM, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 50, 0))); int indexBlank = randomWep.Next(BGWeaponArr.Length); Second.Weapons.Give(BGWeaponArr[indexBlank], 999, true, true); chineseTriad = new PedGroup(); chineseTriad.Add(Second, true); for (int j = 0; j < 6; j++) { int index2 = randomWep.Next(BGWeaponArr.Length); var W2Part1 = World.CreatePed(PedHash.ChiBoss01GMM, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 75, 0))); Function.Call(Hash.SET_PED_AS_GROUP_MEMBER, W2Part1, chineseTriad); chineseTriad.Add(W2Part1, false); Function.Call(Hash.SET_PED_COMBAT_ATTRIBUTES, W2Part1, 46, true); Function.Call(Hash.SET_PED_COMBAT_ABILITY, 100); W2Part1.Weapons.Give(BGWeaponArr[index2], 999, true, true); W2Part1.Health = 400; W2Part1.Armor = 100; W2Part1.Task.FightAgainst(Game.Player.Character); int index1 = randomWep.Next(meleeweaponArr.Length); var W2Part2 = World.CreatePed(PedHash.ChiCold01GMM, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 50, 0))); var W2Part3 = World.CreatePed(PedHash.ChiGoon01GMM, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 75, 0))); var W2Part4 = World.CreatePed(PedHash.ChiGoon02GMM, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 100, 0))); chineseTriad.Add(W2Part2, false); chineseTriad.Add(W2Part3, false); chineseTriad.Add(W2Part4, false); W2Part2.Weapons.Give(meleeweaponArr[index1], 200, true, true); W2Part2.Health = 200; Function.Call(Hash.SET_PED_COMBAT_ABILITY, W2Part2, 50); Function.Call(Hash.SET_PED_COMBAT_ATTRIBUTES, W2Part2, 46, true); W2Part2.Task.FightAgainst(Game.Player.Character); W2Part3.Weapons.Give(meleeweaponArr[index1], 200, true, true); W2Part3.Health = 200; Function.Call(Hash.SET_PED_COMBAT_ABILITY, W2Part3, 50); Function.Call(Hash.SET_PED_COMBAT_ATTRIBUTES, W2Part3, 46, true); W2Part3.Task.FightAgainst(Game.Player.Character); W2Part4.Weapons.Give(meleeweaponArr[index1], 200, true, true); W2Part4.Health = 200; Function.Call(Hash.SET_PED_COMBAT_ABILITY, W2Part4); Function.Call(Hash.SET_PED_COMBAT_ATTRIBUTES, W2Part4, 46, true); W2Part4.Task.FightAgainst(Game.Player.Character); } } public override bool IsDone() { if (chineseTriad != null) { foreach (Ped ped in chineseTriad.ToList()) { if (!ped.IsDead) { return false; } } GTA.UI.Notify("Second wave is dead!"); return true; } return false; } } public class Wave3 : Wave { PedGroup chineseTriad = null; public override void Spawn() { GTA.UI.ShowSubtitle("Final Wave: Big Boss Coming In!"); chineseTriad = new PedGroup(); var W3 = World.CreatePed(PedHash.WeiCheng, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 100, 0))); chineseTriad.Add(W3, true); Function.Call(Hash.SET_PED_COMBAT_ATTRIBUTES, W3, 46, true); Function.Call(Hash.SET_PED_COMBAT_ABILITY, W3, 100); W3.Weapons.Give(WeaponHash.Minigun, 9999, true, true); W3.Health = 2000; W3.Armor = 100; W3.Task.FightAgainst(Game.Player.Character); for (int j = 0; j < 6; j++) { int index2 = randomWep.Next(BGWeaponArr.Length); var W3Part2 = World.CreatePed(PedHash.ChiBoss01GMM, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 75, 0))); Function.Call(Hash.SET_PED_AS_GROUP_MEMBER, W3Part2, chineseTriad); chineseTriad.Add(W3Part2, false); Function.Call(Hash.SET_PED_COMBAT_ATTRIBUTES, W3Part2, 46, true); Function.Call(Hash.SET_PED_COMBAT_ABILITY, 100); W3Part2.Weapons.Give(BGWeaponArr[index2], 999, true, true); W3Part2.Health = 400; W3Part2.Armor = 100; W3Part2.Task.FightAgainst(Game.Player.Character); int index1 = randomWep.Next(meleeweaponArr.Length); var W3Part3 = World.CreatePed(PedHash.ChiCold01GMM, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 50, 0))); var W3Part4 = World.CreatePed(PedHash.ChiGoon01GMM, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 75, 0))); var W3Part5 = World.CreatePed(PedHash.ChiGoon02GMM, Game.Player.Character.GetOffsetInWorldCoords(new Vector3(0, 100, 0))); chineseTriad.Add(W3Part3, false); chineseTriad.Add(W3Part4, false); chineseTriad.Add(W3Part5, false); W3Part3.Weapons.Give(meleeweaponArr[index1], 200, true, true); W3Part3.Health = 200; Function.Call(Hash.SET_PED_COMBAT_ABILITY, W3Part3, 50); Function.Call(Hash.SET_PED_COMBAT_ATTRIBUTES, W3Part3, 46, true); W3Part3.Task.FightAgainst(Game.Player.Character); W3Part4.Weapons.Give(meleeweaponArr[index1], 200, true, true); W3Part4.Health = 200; Function.Call(Hash.SET_PED_COMBAT_ABILITY, W3Part4, 50); Function.Call(Hash.SET_PED_COMBAT_ATTRIBUTES, W3Part5, 46, true); W3Part4.Task.FightAgainst(Game.Player.Character); W3Part5.Weapons.Give(meleeweaponArr[index1], 200, true, true); W3Part5.Health = 200; Function.Call(Hash.SET_PED_COMBAT_ABILITY, W3Part5, 50); Function.Call(Hash.SET_PED_COMBAT_ATTRIBUTES, W3Part5, 46, true); W3Part5.Task.FightAgainst(Game.Player.Character); } } public override bool IsDone() { if (chineseTriad != null) { foreach (Ped ped in chineseTriad.ToList()) { if (!ped.IsDead) { return false; } } GTA.UI.Notify("You have successfully fended off the Chinese Triad attack!"); int randommoney = Function.Call<int>(Hash.GET_RANDOM_INT_IN_RANGE, 2000, 50000); Game.Player.Money = Game.Player.Money + randommoney; GTA.UI.Notify("We have paid you $" + randommoney + ". Good Job!"); return true; } return false; } } public class Class1 : Script { private int current_wave = -1; private Wave[] waves = { new Wave1(), new Wave2(), new Wave3() }; public Ped TestPed; public Vehicle TestVehicle; public Vehicle driveBy; public Class1() { Interval = 1000; this.Tick += OnTick; this.KeyDown += OnKeyDown; this.KeyUp += OnKeyUp; } public void StartNextWave() { current_wave++; if (current_wave < this.waves.Length) { this.waves[current_wave].Spawn(); } } public void OnTick(object sender, EventArgs e) { /* if a wave is running */ if (current_wave >= 0 && current_wave < this.waves.Length) { /* check if it's done */ if (this.waves[current_wave].IsDone()) { StartNextWave(); } } } public void OnKeyUp(object sender, KeyEventArgs e) { } public void OnKeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.K) { //int securityIndex = randomWep.Next(meleeweaponArr.Length); TestVehicle = World.CreateVehicle(VehicleHash.Kuruma2, Game.Player.Character.Position.Around(5)); } if (e.KeyCode == Keys.L) { if (current_wave >= 0 && current_wave < this.waves.Length) { if (this.waves[current_wave].IsDone()) { StartNextWave(); } } } if (e.KeyCode == Keys.P) { StartNextWave(); } } }
}
-
Try adding them all to a relationship group that Hates the player.
-
@mcal9909 Thanks for the help. I have a few other questions. My first question is whether or not I can set a death condition like the one that I set in my code:
public override bool IsDone()
{
if (chineseTriad != null)
{
foreach (Ped ped in chineseTriad.ToList())
{
if (!ped.IsDead){ return false; } }
but instead its the relationship group.
My other question is whether or not this makes them attack me on sight or whether or not I have to attack them first. If I can maybe make a group that will attack me and then make them like the general relationship group, then they would all attack me. Sorry I just really want help.
Thanks for your time.
-
Relationship groups do not work like a traditional "group", A traditional group will act like a unit, all members following its leader. If the leader attacks, the members attack. If someone attacks the leader its members will defend him.
Relationship groups define how peds treat each other, peds in the same relationship group can fight together, but they will not follow each other.
Peds in a relationship group that Hate another Relasionship group will not actively seek out peds they hate, but they will attack the ped on sight and will generally not attack peds who have the same relationship group. (this is how all Ballas peds will fight together against Families, but not attack each other or follow each other)
Relationships can be configured as follows:
Hate>Dislike>Neutral>Respect>Like>Companion.A peds can be in a group and also be in a relasionship group.
-
Check this post out, it has some code regarding relationship groups.
https://forums.gta5-mods.com/post/167378
-
@mcal9909 Yeah I saw that other forum but I still want to clarify something about the relationship groups. How do I actively add more people to the relationship groups as I make them? Thanks for your help!
-
First define your relationship group and its relationships with other groups when your script starts
public static int someRelationshipGroup = World.AddRelationshipGroup("RGROUPNAME"); // make sure the string is unique and unlikley to be used by other mods public static int playerRelationship = Function.Call<int>(Hash.GET_HASH_KEY, "PLAYER"); World.SetRelationshipBetweenGroups(Relationship.Hate, playerRelationship, someRelationshipGroup ); World.SetRelationshipBetweenGroups(Relationship.Hate, someRelationshipGroup , playerRelationship);
Then when you spawn a ped, simply:
Ped.RelationshipGroup = someRelationshipGroup;
-
Last thing I want to check is whether or not I can I check if everyone in the relationship group is dead so I can like move on to the next wave. This is for the new group that is.
-
No, a relasionship groups is not a collection that can be iterated. Its just an
int
Sounds like you want to use aList<Ped>
and add all your peds to that.
-
@mcal9909 So, I can just make a list before the functions and then add them to the list right?
Thanks for all your help btw. You really are the best!
-
yep this might be of some help to you, Once started it will spawn peds at a random location chosen from the List of locations to fight the player every 500ms until there are 15 peds, and keep spawning new peds to replace the dead peds until its told to stop. Not exactly what you are after but it demonstrates how handle alot of peds with a relatively small amount of code.
class EnemyHandler { List<Vector3> SpawnLocations = new List<Vector3> { new Vector3 (-131.695f, -1509.14f, 34.10052f), new Vector3 (-161.0194f, -1515.375f, 33.68655f), new Vector3 (-172.2392f, -1492.894f, 32.55872f) }; Vector3 ClosePos; List<Ped> Enemies = new List<Ped>(); int MaxPeds = 15; int TimeBetweenSpawns = 500; int Time; public bool Started { get; private set; } = false; List<PedHash> pedHashes = new List<PedHash> { PedHash.AvonGoon, PedHash.Juggernaut01M }; Random Rand = new Random(); public EnemyHandler() { } public void Ontick() { if (Started) { if (Game.GameTime > Time + TimeBetweenSpawns && Enemies.Count < MaxPeds) { int index = -1; bool posFound = false; ClosePos = SpawnLocations[0]; foreach (Vector3 v in SpawnLocations) { if (v.DistanceTo(Game.Player.Character.Position) < ClosePos.DistanceTo(Game.Player.Character.Position)) { ClosePos = v; } } while (!posFound) { index = Rand.Next(0, SpawnLocations.Count); if (SpawnLocations[index] != ClosePos) { posFound = true; } } int pedIndex = Rand.Next(0, 2); Ped enemy = World.CreatePed(pedHashes[pedIndex], SpawnLocations[index]); while (enemy == null) { Wait(0); } switch (pedIndex) { case 0: enemy.Weapons.Give(WeaponHash.CarbineRifle, 1000, true, true); Function.Call(Hash.SET_PED_COMBAT_MOVEMENT, enemy, 2); break; case 1: enemy.Weapons.Give(WeaponHash.Minigun, 10000, true, true); enemy.CanSufferCriticalHits = false; enemy.Health = 4000; Function.Call(Hash.SET_PED_COMBAT_MOVEMENT, enemy, 3); break; } Function.Call(Hash.SET_PED_COMBAT_ABILITY, enemy, 100); enemy.FiringPattern = FiringPattern.FullAuto; enemy.CanWrithe = false; enemy.Armor = 100; enemy.RelationshipGroup = enemyTeam; enemy.AlwaysKeepTask = true; enemy.Task.FightAgainst(Game.Player.Character); enemy.AddBlip(); enemy.CurrentBlip.IsFriendly = false; Enemies.Add(enemy); Time = Game.GameTime; } } CheckPeds(); } public void Start() { Started = true; } public void Stop() { Started = false; } void CheckPeds() { if (Enemies.Count > 0) { foreach (Ped p in Enemies.ToList()) { if (p == null || !p.Exists()) { Enemies.Remove(p); } else if (p.IsDead) { p.CurrentBlip.Remove(); Enemies.Remove(p); } } } } void RemoveEnemies() { foreach (Ped p in Enemies.ToList()) { p.CurrentBlip.Remove(); Enemies.Remove(p); } } }
-
@mcal9909 So with this method can I make it so that if it reaches like 30 people it will stop. Also where is the part where it waits until 15 people. I am just a little confused about that. Thanks for your help so far though.
-
int MaxPeds = 15; //This is how many peds can be alive at anyone time.
-
@mcal9909 I saw in your code that you had make enemy blips for them. I added them into my code and I don't think that blips update with their movement. I would really appreciate it if you would help me with that. I also want to know how to make the blips smaller because they are quite big and cluttered.
-
@briancatmaster Aslong the blip is assigned to an eitity with AddBlip(), it will follow them that entity
-
@mcal9909 Do you know how to make those blips smaller I can't make them smaller because they don't let me put in decimals or fractions because its a float. Thanks for all your help so far.
-
@briancatmaster
Just set the scale, Ped.CurrentBlip.Scale = 0.5f;