Dear forum users! In compliance with the new European GDPR regulations, we'd just like to inform you that if you have an account, your email address is stored in our database. We do not share your information with third parties, and your email address and password are encrypted for security reasons.

New to the forum? Say hello in this topic! Also make sure to read the rules.

Need a Script for making Squads of soldiers!

Share questions, scripts and tutorials related to the ScriptAPI in SFD.
Forum rules
By using the forum you agree to the following rules.
Post Reply
User avatar
Mr Argon
Fighter
Fighter
Posts: 45
Joined: Sat Mar 09, 2019 2:22 am
SFD Account: Argón (steam)
SFD Alias: Mr. Argon
Started SFD: Pre-Alpha 1.8.2c
Location: Argentina
Gender:
Age: 16

Need a Script for making Squads of soldiers!

Post by Mr Argon » Thu Jan 09, 2020 4:34 am

Hi! I'm working on a campaign that's very similar to Half-Life, you know, there's soldiers and special commands fighting with aliens. I'm currently stuck because I've been programming some AI scripts for the soldiers to fight using a Squad strategy.

The schedules I've planned are very simple.

-Soldiers go on safe spots to reload and when there's a lot of danger.
-Soldiers will divide themselves into Squads for better strategies, basically, when Squad A is hiding behind sandbags, Squad B is firing from different angles, then, the Squads will alternate their schedules so that Squad A is in attack mode and Squad B is on retreat mode.

The problem here is that I can't figure out how to make the soldiers spawn being from a certain Squad. I'll use many PlayerSpawnTriggers and some of them will spawn soldiers from different Squads, I mean, they're fixed, no need of a soldier changing his Squad on mid-game.

I'll paste here my entire script, you'll see incomplete lines and methods that I was testing to see if it works, having no positive results.

Hope anyone can help me. Thanks!
        // SQUAD SETTING & NPC FIGHTING
        private IProfileClothingItem Clh_Helmet = (Game.GetSingleObjectByCustomID("OpProfile") as IObjectPlayerProfileInfo).GetProfile().Head;

        public IPlayer[] GetSoldiers() { return (from Q in Game.GetPlayers() where (Q.IsAIControlled && !Q.IsDead && Q.GetTeam() == PlayerTeam.Team1 && Q != plr_player && Q.GetProfile().Head == Clh_Helmet) select Q).ToArray(); }

        public IObject CurrentTarget = null;

        public IObject[] AvailableSpots()
        {
            return Game.GetObjectsByCustomID("SafeSpot");
        }

        // Squad Setting.

        public void SetSquad(TriggerArgs args, string squad)
        {
            (args.Sender as IObject)
        }

        // Soldier AI's.

        public void SetSquadA(TriggerArgs args)
        {
            IPlayer player = (args.Caller as IObjectPlayerSpawnTrigger).GetLastCreatedPlayer();
        }

        // Update Soldiers to Retreat or Fight depending on circunstances.
        public void UpdateSoldiers(TriggerArgs args)
        {
            foreach (IPlayer soldier in GetSoldiers())
            {
                BotBehaviorSet soldiersRetreatBehavior = soldier.GetBotBehaviorSet();
                soldiersRetreatBehavior.EliminateEnemies = false;
                soldiersRetreatBehavior.SearchForItems = false;
                soldiersRetreatBehavior.AggroRange = 0f;
                soldiersRetreatBehavior.GuardRange = 30f;
                soldiersRetreatBehavior.ChaseRange = 45f;
                soldiersRetreatBehavior.TeamLineUp = true;
                soldiersRetreatBehavior.OffensiveDiveLevel = 0f;
                soldiersRetreatBehavior.OffensiveEnrageLevel = 0.35f;
                soldiersRetreatBehavior.OffensiveClimbingLevel = 0f;
                soldiersRetreatBehavior.SeekCoverWhileShooting = 1f;
                soldier.SetBotBehaviorSet(soldiersRetreatBehavior);
                IObject myTarget = (from Q in AvailableSpots() orderby Vector2.Distance(soldier.GetWorldPosition(), Q.GetWorldPosition()) ascending select Q).FirstOrDefault();
                soldier.SetGuardTarget(myTarget);

            }
        }
2 x
I'м д Liттlэ оdd... sтill саи livе шiтн тнат.

User avatar
JakSparro98
Superfighter
Superfighter
Posts: 517
Joined: Fri Jul 15, 2016 7:56 pm
Started SFD: PreAlpha 1.0.5
Location: Rome, Italy
Gender:
Age: 21

Post by JakSparro98 » Thu Jan 09, 2020 8:27 pm

I assume your idea of a squad cannot be achieved by a simple vanilla team assignment, the concept I was thinking of is defining a class, call it simply "Squad" for instance and it contains the squad name and a list of all the bots (their UIDs) that belong to that squad, if a bot needs to know what his squad is, he can call a method for getting a the name of the squad.
1 x

User avatar
Mr Argon
Fighter
Fighter
Posts: 45
Joined: Sat Mar 09, 2019 2:22 am
SFD Account: Argón (steam)
SFD Alias: Mr. Argon
Started SFD: Pre-Alpha 1.8.2c
Location: Argentina
Gender:
Age: 16

Post by Mr Argon » Thu Jan 09, 2020 9:30 pm

That's what I was trying to do with the SetSquad void.

Should I declare a public class or something like that?

I'm a c# learner, I understand many of the things I use here, but I often get confused by those "public" and "private" thing. I know how they are used in other enviorments, but can't figure out what's the difference between them in the SFD script API.
0 x
I'м д Liттlэ оdd... sтill саи livе шiтн тнат.

User avatar
Gurt
Lead Programmer
Lead Programmer
Posts: 1717
Joined: Sun Feb 28, 2016 3:22 pm
Title: Lead programmer
Started SFD: Made it!
Location: Sweden
Gender:
Age: 29

Post by Gurt » Thu Jan 09, 2020 9:33 pm

The PlayerSpawnTrigger uses CreateTriggerArgs derived from TriggerArgs.
In your script method from the trigger you should be able to do something like this (haven't tried compiling it, writing on the fly):

Code: Select all

public void PlayerSpawnedFromSpawnTrigger(TriggerArgs args)
{
   CreateTriggerArgs createArgs = (CreateTriggerArgs )args;
   IPlayer createdPlayer = (IPlayer)createArgs.CreatedObject;
   IObjectPlayerSpawnTrigger trigger = (IObjectPlayerSpawnTrigger)createArgs.Caller;
   if (trigger.CustomID == "SquadA") {
	  // SpawnTrigger with CustomID "SquadA" has created player "createdPlayer".
	  
   }
   
   // Maybe use CustomID from PlayerSpawnTrigger to determine Squad assignment
   SetSquad(createdPlayer, trigger.CustomID);
}

public void SetSquad(IPlayer player, string squad)
{
  switch (squad)
  {
	case "SquadA": 
	{
		// Do some stuff
	}
	break;
	case "SquadB": 
	{
		// Do some stuff
	}
	break;
  }
}
You are trying to do some very complex actions for the bots:
-Soldiers go on safe spots to reload and when there's a lot of danger.
-Soldiers will divide themselves into Squads for better strategies, basically, when Squad A is hiding behind sandbags, Squad B is firing from different angles, then, the Squads will alternate their schedules so that Squad A is in attack mode and Squad B is on retreat mode.

Exactly how you want the logic to be deisgned is up to you. Check out how we made certain boss run to a certain spot for example if you want the bots to run away.
Just note that you can only influence how the bots behave with the BotBehaviors. If you need to let the bots perform specific actions you need to check out CommandTriggers which allows you to control exactly how the bots move around but requires a lot more work, but you could use the CommandTriggers for a specific action - perhaps to force bots to take cover when near a cover. Then swap back to the ordinary BotBehavior.
0 x
Gurt

User avatar
Mr Argon
Fighter
Fighter
Posts: 45
Joined: Sat Mar 09, 2019 2:22 am
SFD Account: Argón (steam)
SFD Alias: Mr. Argon
Started SFD: Pre-Alpha 1.8.2c
Location: Argentina
Gender:
Age: 16

Post by Mr Argon » Thu Jan 09, 2020 10:04 pm

Thanks! That's what I need. Yeah, I have no problem with bot behavior, the only issue I had is this.

I want in where you placed "// Do some stuff" I only want the soldiers to know wich squad they're part of. So that I can make something like this in certain situations.
foreach IPlayer soldier in GetSoldiers() { if soldier.squad == "A" ...}
just some kind of variable I can check if they're of a certain Squad or not.
0 x
I'м д Liттlэ оdd... sтill саи livе шiтн тнат.

User avatar
JakSparro98
Superfighter
Superfighter
Posts: 517
Joined: Fri Jul 15, 2016 7:56 pm
Started SFD: PreAlpha 1.0.5
Location: Rome, Italy
Gender:
Age: 21

Post by JakSparro98 » Fri Jan 10, 2020 12:18 am

Mr Argon wrote:
Thu Jan 09, 2020 9:30 pm
[..]
I'm a c# learner, I understand many of the things I use here, but I often get confused by those "public" and "private" thing. I know how they are used in other enviorments, but can't figure out what's the difference between them in the SFD script API.
Just think of the sfd script environment as the body of a bigger wrapper class, something like the one defined here

Code: Select all

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using SFDGameScriptInterface;



    class GameScript : GameScriptInterface
    {
        public GameScript() : base(null) { }



        // Run code before triggers marked with "Activate on startup" but after players spawn from SpawnMarkers.
        public void OnStartup()
        {
            HelloWorld();
        }

        // Run code after triggers marked with "Activate on startup".
        public void AfterStartup()
        {
        }
        
        // Run code on map restart (or script disabled).
        public void OnShutdown()
        {
        }

        void HelloWorld()
        {
            Game.ShowPopupMessage("Hello World!");
        }

    }

original snippet from this thread.

the only reasons for using public is for allowing triggers to "see" the method when calling their script method field or to expose methods/fields of inner classes.
Mr Argon wrote:
Thu Jan 09, 2020 9:30 pm
[..]
Should I declare a public class or something like that?
[..]
Simply declare a dictionary<Integer,String> and when you set the squad you can add both the bot's ID and the squad name into the dictionary, then you can easily retrieve back the squad name if you know the bot's ID

Code: Select all

Dictionary <int,String> Squads = new Dictionary<int,String>();
void SetSquad(IPlayer player, string squad)
{
Squads.Add(player.UniqueID,squad);
}

String GetSquad(IPlayer player)
{
return Squads[player.UniqueID];
}
0 x

User avatar
Mr Argon
Fighter
Fighter
Posts: 45
Joined: Sat Mar 09, 2019 2:22 am
SFD Account: Argón (steam)
SFD Alias: Mr. Argon
Started SFD: Pre-Alpha 1.8.2c
Location: Argentina
Gender:
Age: 16

Post by Mr Argon » Fri Jan 10, 2020 12:35 am

Thank you two a lot! I'll investigate a little bit more about list and dictionaries on c#, but I get the idea. At least I can resume my work now. Hope I can finish this campaign by the way, because most of the campaigns I start, I end up deleting them because I can't manage to create a good gameplay.

Also, by the way, if you're interested on this, I may need to kill and respawn soldiers each one belonging to the same squad they did before. By using the same PlayerSpawnTrigger.
Last edited by KliPeH on Fri Jan 10, 2020 2:20 pm, edited 1 time in total.
Reason: Merged a double post.
0 x
I'м д Liттlэ оdd... sтill саи livе шiтн тнат.

Post Reply