AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting (https://forums.alliedmods.net/forumdisplay.php?f=107)
-   -   Solved [TF2] Problem with Bot Creation Plugin (https://forums.alliedmods.net/showthread.php?t=330002)

ThatKidWhoGames 01-16-2021 13:27

[TF2] Problem with Bot Creation Plugin
 
Hello,

I am currently writing a plugin where admins can create bots (fake clients) using the command sm_bot. If no arguments are supplied, it creates a bot and sets their team to a random team and their class to a random class. If arguments are given, it sets the bots team and class accordingly. However, I am having a strange issue when it comes to setting the bots team and class to be random when no arguments are given. Using the command creating a bot for the first time without arguments initially works perfectly fine, and creates the bot correctly with a random team and class. However, every time after that, it sets their team to red and their class to engineer. I am certain that there are no other conflicting plugins and I have tried restarting my server and changing the map. When arguments are given for the command, the bot is created correctly and there are never issues with it. Here is my code:
PHP Code:

#include <sourcemod>
#include <tf2_stocks>

public void OnPluginStart()
{
    
RegAdminCmd("sm_bot"Command_BotADMFLAG_CHEATS"Create a bot");
}

public 
Action Command_Bot(int iClientint iArgs)
{
    
TFTeam team TF2_GetRandomTeam();
    
TFClassType class = TF2_GetRandomClass();
    if (
iArgs 0)
    {
        
/* Get the first argument */
        
char sArg1[32];
        
GetCmdArg(1sArg1sizeof(sArg1));
        
team TF2_GetTeamFromString(sArg1);
        if (
team TFTeam_Red)
        {
            
ReplyToCommand(iClient"[SM] Invalid team specified!");
            return 
Plugin_Handled;
        }

        if (
iArgs 1)
        {
            
/* Get the second argument */
            
char sArg2[32];
            
GetCmdArg(2sArg2sizeof(sArg2));
            class = 
TF2_GetClassFromString(sArg2);
            if (class == 
TFClass_Unknown)
            {
                
ReplyToCommand(iClient"[SM] Invalid class specified!");
                return 
Plugin_Handled;
            }
        }
    }

    
ReplyToCommand(iClient"[SM] team == %d"team);
    
ReplyToCommand(iClient"[SM] class == %d", class);

    
char sTeam[32], sClass[32];
    
TF2_GetTeamName(teamsTeamsizeof(sTeam));
    
TF2_GetClassName(class, sClasssizeof(sClass));

    
CapitalizeFirstLetter(sTeam);
    
CapitalizeFirstLetter(sClass);

    
char sName[MAX_NAME_LENGTH];
    
Format(sNamesizeof(sName), "%s %s #%i"sTeamsClassTF2_GetBotCount(team, class));
    if (!
TF2_CreateBot(sNameteam, class))
    {
        
ReplyToCommand(iClient"[SM] Failure creating bot!");
        return 
Plugin_Handled;
    }

    
ReplyToCommand(iClient"[SM] Successfully created bot!");
    return 
Plugin_Handled;
}

stock TFTeam TF2_GetRandomTeam()
{
    return 
view_as<TFTeam>(GetRandomInt(23));
}

stock TFClassType TF2_GetRandomClass()
{
    return 
view_as<TFClassType>(GetRandomInt(19));
}

stock TFTeam TF2_GetTeamFromString(const char[] sBuffer)
{
    if (
StrEqual(sBuffer"1"false) || StrEqual(sBuffer"spectator"false))
    {
        return 
TFTeam_Spectator;
    }

    if (
StrEqual(sBuffer"2"false) || StrEqual(sBuffer"red"false))
    {
        return 
TFTeam_Red;
    }

    if (
StrEqual(sBuffer"3"false) || StrEqual(sBuffer"blue"false))
    {
        return 
TFTeam_Blue;
    }

    return 
TFTeam_Unassigned;
}

stock void TF2_GetTeamName(TFTeam teamchar[] sBufferint iMaxlength)
{
    switch (
team)
    {
        case 
TFTeam_Unassigned:
        {
            
Format(sBufferiMaxlength"unassigned");
        }

        case 
TFTeam_Spectator:
        {
            
Format(sBufferiMaxlength"spectator");
        }

        case 
TFTeam_Red:
        {
            
Format(sBufferiMaxlength"red");
        }

        case 
TFTeam_Blue:
        {
            
Format(sBufferiMaxlength"blue");
        }
    }
}

// This is basically TF2_GetClass() but it works better
stock TFClassType TF2_GetClassFromString(const char[] sBuffer)
{
    if (
StrEqual(sBuffer"scout"false))
    {
        return 
TFClass_Scout;
    }

    if (
StrEqual(sBuffer"soldier"false))
    {
        return 
TFClass_Soldier;
    }

    if (
StrEqual(sBuffer"pyro"false))
    {
        return 
TFClass_Pyro;
    }

    if (
StrEqual(sBuffer"demoman"false))
    {
        return 
TFClass_DemoMan;
    }

    if (
StrEqual(sBuffer"heavy"false))
    {
        return 
TFClass_Heavy;
    }

    if (
StrEqual(sBuffer"engineer"false))
    {
        return 
TFClass_Engineer;
    }

    if (
StrEqual(sBuffer"medic"false))
    {
        return 
TFClass_Medic;
    }

    if (
StrEqual(sBuffer"sniper"false))
    {
        return 
TFClass_Sniper;
    }

    if (
StrEqual(sBuffer"spy"false))
    {
        return 
TFClass_Spy;
    }

    return 
TFClass_Unknown;
}

stock void TF2_GetClassName(TFClassType class, char[] sBufferint iMaxlength)
{
    switch (class)
    {
        case 
TFClass_Scout:
        {
            
Format(sBufferiMaxlength"scout");
        }

        case 
TFClass_Soldier:
        {
            
Format(sBufferiMaxlength"soldier");
        }

        case 
TFClass_Pyro:
        {
            
Format(sBufferiMaxlength"pyro");
        }

        case 
TFClass_DemoMan:
        {
            
Format(sBufferiMaxlength"demoman");
        }

        case 
TFClass_Heavy:
        {
            
Format(sBufferiMaxlength"heavy");
        }

        case 
TFClass_Engineer:
        {
            
Format(sBufferiMaxlength"engineer");
        }

        case 
TFClass_Medic:
        {
            
Format(sBufferiMaxlength"medic");
        }

        case 
TFClass_Sniper:
        {
            
Format(sBufferiMaxlength"sniper");
        }

        case 
TFClass_Spy:
        {
            
Format(sBufferiMaxlength"spy");
        }

        case 
TFClass_Unknown:
        {
            
Format(sBufferiMaxlength"unknown");
        }
    }
}

stock int TF2_GetBotCount(TFTeam teamTFClassType class)
{
    
int iCount 1;
    for (
int i 1<= MaxClientsi++)
    {
        if (
IsClientInGame(i) && IsFakeClient(i) && TF2_GetClientTeam(i) == team && TF2_GetPlayerClass(i) == class)
        {
            
iCount++;
        }
    }

    return 
iCount;
}

stock bool TF2_CreateBot(const char[] sNameTFTeam teamTFClassType class)
{
    
int iBot CreateFakeClient(sName);
    if (
iBot != 0)
    {
        
TF2_ChangeClientTeam(iBotteam);
        
TF2_SetPlayerClass(iBot, class);
        
TF2_RespawnPlayer(iBot);
        return 
true;
    }

    return 
false;
}

stock void CapitalizeFirstLetter(char[] sBuffer)
{
    
sBuffer[0] = CharToUpper(sBuffer[0]);


Thank you,
Grant

PC Gamer 01-17-2021 12:33

Re: [TF2] Problem with Bot Creation Plugin
 
Are you trying to create Puppet Bots? I'm already running Bots on my server. When I use the code above the new Bot is created and it just stands there without moving. The server console will display "Cannot verify load for invalid steam ID [A:1:3415:1]".

Anyway... I was able to reproduce and correct the Engineer error. I'm certainly no expert but I believe the SourceMod GetRandomInt function is to blame in this case. It started working correctly when I replaced it with GetRandomUInt. The invalid steam ID problem still exists.

Edited code:
PHP Code:

#include <sourcemod>
#include <tf2_stocks>

public void OnPluginStart()
{
    
RegAdminCmd("sm_bot"Command_BotADMFLAG_CHEATS"Create a bot");
}

public 
Action Command_Bot(int iClientint iArgs)
{
    
TFTeam team TF2_GetRandomTeam();
    
TFClassType class = TF2_GetRandomClass();
    if (
iArgs 0)
    {
        
/* Get the first argument */
        
char sArg1[32];
        
GetCmdArg(1sArg1sizeof(sArg1));
        
team TF2_GetTeamFromString(sArg1);
        if (
team TFTeam_Red)
        {
            
ReplyToCommand(iClient"[SM] Invalid team specified!");
            return 
Plugin_Handled;
        }

        if (
iArgs 1)
        {
            
/* Get the second argument */
            
char sArg2[32];
            
GetCmdArg(2sArg2sizeof(sArg2));
            class = 
TF2_GetClassFromString(sArg2);
            if (class == 
TFClass_Unknown)
            {
                
ReplyToCommand(iClient"[SM] Invalid class specified!");
                return 
Plugin_Handled;
            }
        }
    }

    
ReplyToCommand(iClient"[SM] team == %d"team);
    
ReplyToCommand(iClient"[SM] class == %d", class);

    
char sTeam[32], sClass[32];
    
TF2_GetTeamName(teamsTeamsizeof(sTeam));
    
TF2_GetClassName(class, sClasssizeof(sClass));

    
CapitalizeFirstLetter(sTeam);
    
CapitalizeFirstLetter(sClass);

    
char sName[MAX_NAME_LENGTH];
    
Format(sNamesizeof(sName), "%s %s #%i"sTeamsClassTF2_GetBotCount(team, class));
    if (!
TF2_CreateBot(sNameteam, class))
    {
        
ReplyToCommand(iClient"[SM] Failure creating bot!");
        return 
Plugin_Handled;
    }

    
ReplyToCommand(iClient"[SM] Successfully created bot!");
    return 
Plugin_Handled;
}

stock TFTeam TF2_GetRandomTeam()
{
    return 
view_as<TFTeam>(GetRandomUInt(23));
}

stock TFClassType TF2_GetRandomClass()
{
    return 
view_as<TFClassType>(GetRandomUInt(19));
}

stock TFTeam TF2_GetTeamFromString(const char[] sBuffer)
{
    if (
StrEqual(sBuffer"1"false) || StrEqual(sBuffer"spectator"false))
    {
        return 
TFTeam_Spectator;
    }

    if (
StrEqual(sBuffer"2"false) || StrEqual(sBuffer"red"false))
    {
        return 
TFTeam_Red;
    }

    if (
StrEqual(sBuffer"3"false) || StrEqual(sBuffer"blue"false))
    {
        return 
TFTeam_Blue;
    }

    return 
TFTeam_Unassigned;
}

stock void TF2_GetTeamName(TFTeam teamchar[] sBufferint iMaxlength)
{
    switch (
team)
    {
    case 
TFTeam_Unassigned:
        {
            
Format(sBufferiMaxlength"unassigned");
        }

    case 
TFTeam_Spectator:
        {
            
Format(sBufferiMaxlength"spectator");
        }

    case 
TFTeam_Red:
        {
            
Format(sBufferiMaxlength"red");
        }

    case 
TFTeam_Blue:
        {
            
Format(sBufferiMaxlength"blue");
        }
    }
}

// This is basically TF2_GetClass() but it works better
stock TFClassType TF2_GetClassFromString(const char[] sBuffer)
{
    if (
StrEqual(sBuffer"scout"false))
    {
        return 
TFClass_Scout;
    }

    if (
StrEqual(sBuffer"soldier"false))
    {
        return 
TFClass_Soldier;
    }

    if (
StrEqual(sBuffer"pyro"false))
    {
        return 
TFClass_Pyro;
    }

    if (
StrEqual(sBuffer"demoman"false))
    {
        return 
TFClass_DemoMan;
    }

    if (
StrEqual(sBuffer"heavy"false))
    {
        return 
TFClass_Heavy;
    }

    if (
StrEqual(sBuffer"engineer"false))
    {
        return 
TFClass_Engineer;
    }

    if (
StrEqual(sBuffer"medic"false))
    {
        return 
TFClass_Medic;
    }

    if (
StrEqual(sBuffer"sniper"false))
    {
        return 
TFClass_Sniper;
    }

    if (
StrEqual(sBuffer"spy"false))
    {
        return 
TFClass_Spy;
    }

    return 
TFClass_Unknown;
}

stock void TF2_GetClassName(TFClassType class, char[] sBufferint iMaxlength)
{
    switch (class)
    {
    case 
TFClass_Scout:
        {
            
Format(sBufferiMaxlength"scout");
        }

    case 
TFClass_Soldier:
        {
            
Format(sBufferiMaxlength"soldier");
        }

    case 
TFClass_Pyro:
        {
            
Format(sBufferiMaxlength"pyro");
        }

    case 
TFClass_DemoMan:
        {
            
Format(sBufferiMaxlength"demoman");
        }

    case 
TFClass_Heavy:
        {
            
Format(sBufferiMaxlength"heavy");
        }

    case 
TFClass_Engineer:
        {
            
Format(sBufferiMaxlength"engineer");
        }

    case 
TFClass_Medic:
        {
            
Format(sBufferiMaxlength"medic");
        }

    case 
TFClass_Sniper:
        {
            
Format(sBufferiMaxlength"sniper");
        }

    case 
TFClass_Spy:
        {
            
Format(sBufferiMaxlength"spy");
        }

    case 
TFClass_Unknown:
        {
            
Format(sBufferiMaxlength"unknown");
        }
    }
}

stock int TF2_GetBotCount(TFTeam teamTFClassType class)
{
    
int iCount 1;
    for (
int i 1<= MaxClientsi++)
    {
        if (
IsClientInGame(i) && IsFakeClient(i) && TF2_GetClientTeam(i) == team && TF2_GetPlayerClass(i) == class)
        {
            
iCount++;
        }
    }

    return 
iCount;
}

stock bool TF2_CreateBot(const char[] sNameTFTeam teamTFClassType class)
{
    
int iBot CreateFakeClient(sName);
    
PrintToChatAll("Debug: Creating %s, %s, %s"sNameteam, class);
    if (
iBot != 0)
    {
        
TF2_ChangeClientTeam(iBotteam);
        
TF2_SetPlayerClass(iBot, class);
        
TF2_RespawnPlayer(iBot);
        return 
true;
    }

    return 
false;
}

stock void CapitalizeFirstLetter(char[] sBuffer)
{
    
sBuffer[0] = CharToUpper(sBuffer[0]);


int GetRandomUInt(int minint max)
{
    return 
RoundToFloor(GetURandomFloat() * (max min 1)) + min;



ThatKidWhoGames 01-17-2021 13:49

Re: [TF2] Problem with Bot Creation Plugin
 
Quote:

Originally Posted by PC Gamer (Post 2732984)
Are you trying to create Puppet Bots? I'm already running Bots on my server. When I use the code above the new Bot is created and it just stands there without moving. The server console will display "Cannot verify load for invalid steam ID [A:1:3415:1]".

Anyway... I was able to reproduce and correct the Engineer error. I'm certainly no expert but I believe the SourceMod GetRandomInt function is to blame in this case. It started working correctly when I replaced it with GetRandomUInt. The invalid steam ID problem still exists.

Edited code:
PHP Code:

#include <sourcemod>
#include <tf2_stocks>

public void OnPluginStart()
{
    
RegAdminCmd("sm_bot"Command_BotADMFLAG_CHEATS"Create a bot");
}

public 
Action Command_Bot(int iClientint iArgs)
{
    
TFTeam team TF2_GetRandomTeam();
    
TFClassType class = TF2_GetRandomClass();
    if (
iArgs 0)
    {
        
/* Get the first argument */
        
char sArg1[32];
        
GetCmdArg(1sArg1sizeof(sArg1));
        
team TF2_GetTeamFromString(sArg1);
        if (
team TFTeam_Red)
        {
            
ReplyToCommand(iClient"[SM] Invalid team specified!");
            return 
Plugin_Handled;
        }

        if (
iArgs 1)
        {
            
/* Get the second argument */
            
char sArg2[32];
            
GetCmdArg(2sArg2sizeof(sArg2));
            class = 
TF2_GetClassFromString(sArg2);
            if (class == 
TFClass_Unknown)
            {
                
ReplyToCommand(iClient"[SM] Invalid class specified!");
                return 
Plugin_Handled;
            }
        }
    }

    
ReplyToCommand(iClient"[SM] team == %d"team);
    
ReplyToCommand(iClient"[SM] class == %d", class);

    
char sTeam[32], sClass[32];
    
TF2_GetTeamName(teamsTeamsizeof(sTeam));
    
TF2_GetClassName(class, sClasssizeof(sClass));

    
CapitalizeFirstLetter(sTeam);
    
CapitalizeFirstLetter(sClass);

    
char sName[MAX_NAME_LENGTH];
    
Format(sNamesizeof(sName), "%s %s #%i"sTeamsClassTF2_GetBotCount(team, class));
    if (!
TF2_CreateBot(sNameteam, class))
    {
        
ReplyToCommand(iClient"[SM] Failure creating bot!");
        return 
Plugin_Handled;
    }

    
ReplyToCommand(iClient"[SM] Successfully created bot!");
    return 
Plugin_Handled;
}

stock TFTeam TF2_GetRandomTeam()
{
    return 
view_as<TFTeam>(GetRandomUInt(23));
}

stock TFClassType TF2_GetRandomClass()
{
    return 
view_as<TFClassType>(GetRandomUInt(19));
}

stock TFTeam TF2_GetTeamFromString(const char[] sBuffer)
{
    if (
StrEqual(sBuffer"1"false) || StrEqual(sBuffer"spectator"false))
    {
        return 
TFTeam_Spectator;
    }

    if (
StrEqual(sBuffer"2"false) || StrEqual(sBuffer"red"false))
    {
        return 
TFTeam_Red;
    }

    if (
StrEqual(sBuffer"3"false) || StrEqual(sBuffer"blue"false))
    {
        return 
TFTeam_Blue;
    }

    return 
TFTeam_Unassigned;
}

stock void TF2_GetTeamName(TFTeam teamchar[] sBufferint iMaxlength)
{
    switch (
team)
    {
    case 
TFTeam_Unassigned:
        {
            
Format(sBufferiMaxlength"unassigned");
        }

    case 
TFTeam_Spectator:
        {
            
Format(sBufferiMaxlength"spectator");
        }

    case 
TFTeam_Red:
        {
            
Format(sBufferiMaxlength"red");
        }

    case 
TFTeam_Blue:
        {
            
Format(sBufferiMaxlength"blue");
        }
    }
}

// This is basically TF2_GetClass() but it works better
stock TFClassType TF2_GetClassFromString(const char[] sBuffer)
{
    if (
StrEqual(sBuffer"scout"false))
    {
        return 
TFClass_Scout;
    }

    if (
StrEqual(sBuffer"soldier"false))
    {
        return 
TFClass_Soldier;
    }

    if (
StrEqual(sBuffer"pyro"false))
    {
        return 
TFClass_Pyro;
    }

    if (
StrEqual(sBuffer"demoman"false))
    {
        return 
TFClass_DemoMan;
    }

    if (
StrEqual(sBuffer"heavy"false))
    {
        return 
TFClass_Heavy;
    }

    if (
StrEqual(sBuffer"engineer"false))
    {
        return 
TFClass_Engineer;
    }

    if (
StrEqual(sBuffer"medic"false))
    {
        return 
TFClass_Medic;
    }

    if (
StrEqual(sBuffer"sniper"false))
    {
        return 
TFClass_Sniper;
    }

    if (
StrEqual(sBuffer"spy"false))
    {
        return 
TFClass_Spy;
    }

    return 
TFClass_Unknown;
}

stock void TF2_GetClassName(TFClassType class, char[] sBufferint iMaxlength)
{
    switch (class)
    {
    case 
TFClass_Scout:
        {
            
Format(sBufferiMaxlength"scout");
        }

    case 
TFClass_Soldier:
        {
            
Format(sBufferiMaxlength"soldier");
        }

    case 
TFClass_Pyro:
        {
            
Format(sBufferiMaxlength"pyro");
        }

    case 
TFClass_DemoMan:
        {
            
Format(sBufferiMaxlength"demoman");
        }

    case 
TFClass_Heavy:
        {
            
Format(sBufferiMaxlength"heavy");
        }

    case 
TFClass_Engineer:
        {
            
Format(sBufferiMaxlength"engineer");
        }

    case 
TFClass_Medic:
        {
            
Format(sBufferiMaxlength"medic");
        }

    case 
TFClass_Sniper:
        {
            
Format(sBufferiMaxlength"sniper");
        }

    case 
TFClass_Spy:
        {
            
Format(sBufferiMaxlength"spy");
        }

    case 
TFClass_Unknown:
        {
            
Format(sBufferiMaxlength"unknown");
        }
    }
}

stock int TF2_GetBotCount(TFTeam teamTFClassType class)
{
    
int iCount 1;
    for (
int i 1<= MaxClientsi++)
    {
        if (
IsClientInGame(i) && IsFakeClient(i) && TF2_GetClientTeam(i) == team && TF2_GetPlayerClass(i) == class)
        {
            
iCount++;
        }
    }

    return 
iCount;
}

stock bool TF2_CreateBot(const char[] sNameTFTeam teamTFClassType class)
{
    
int iBot CreateFakeClient(sName);
    
PrintToChatAll("Debug: Creating %s, %s, %s"sNameteam, class);
    if (
iBot != 0)
    {
        
TF2_ChangeClientTeam(iBotteam);
        
TF2_SetPlayerClass(iBot, class);
        
TF2_RespawnPlayer(iBot);
        return 
true;
    }

    return 
false;
}

stock void CapitalizeFirstLetter(char[] sBuffer)
{
    
sBuffer[0] = CharToUpper(sBuffer[0]);


int GetRandomUInt(int minint max)
{
    return 
RoundToFloor(GetURandomFloat() * (max min 1)) + min;



Hello,

Thank you for the reply! That did the trick, thanks! Yeah, the bots are intended to not be able to move. Out of curiosity, what made the issue occur with the GetRandomInt() function? Is it something to do with caching or along those lines?

Thank you,
Grant


All times are GMT -4. The time now is 17:16.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.