Raised This Month: $2 Target: $400
 0% 

[H3LP] PlayerClass Fortress Forever


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
DarthMan
Veteran Member
Join Date: Aug 2011
Old 11-25-2017 , 11:05   [H3LP] PlayerClass Fortress Forever
Reply With Quote #1

Could someone help me in getting and setting the player class id for the game Fortress Forever?

Code:
stock int GetPlayerClass(int client) {     if(!IsPlayer(client))         return 0;         if (GetEngineVersion() == Engine_DarkMessiah)         return GetEntProp(client, Prop_Send, "m_iPlayerClass");         return GetEntProp(client, Prop_Send, "m_iClass"); } stock int SetPlayerClass(int client, int class, bool persistant=false) {     if(!IsPlayer(client))         return 0;         if (GetEngineVersion() == Engine_DarkMessiah)         SetEntProp(client, Prop_Send, "m_iPlayerClass", class);     else         SetEntProp(client, Prop_Send, "m_iClass", class);         if(persistent)         SetEntProp(client, Prop_Send, "m_iDesiredPlayerClass", class);         return 1; }

I tried to print the player class when typing console command classname but it throwed an error so I guess that something might be wrong on the stock maybe?
I got the netprops and it seems that FF indded contains the m_iClass prop.

Thanks !

Last edited by DarthMan; 11-25-2017 at 11:17.
DarthMan is offline
DarthMan
Veteran Member
Join Date: Aug 2011
Old 11-26-2017 , 05:55   Re: [H3LP] PlayerClass Fortress Forever
Reply With Quote #2

The error I'm getting : L 11/26/2017 - 12:53:50: [SM] Exception reported: Property "m_iClass" not found (entity 1/player)

I can conrifm that the property m_iClass exists on FF.
DarthMan is offline
hlstriker
Green Gaben
Join Date: Mar 2006
Location: OH-IO!
Old 11-28-2017 , 05:02   Re: [H3LP] PlayerClass Fortress Forever
Reply With Quote #3

You will want to use "m_iClassStatus". But that won't work to set the class, so read all to the end.

GetClassSlot
PHP Code:
GetClassSlot(iClient)
{
    return (
GetEntProp(iClientProp_Send"m_iClassStatus") & 0x0000000F);

SetClassForClient
PHP Code:
SetClassForClient(iClientiSlot)
{
    
SetEntProp(iClientProp_Send"m_iClassStatus"iSlot 0x0000000F);

However, because "m_iNextClass" is not changed the server will put you back to your original class. The variable "m_iNextClass" is what ultimately decides what class you will be when you respawn. The problem is "m_iNextClass" is not accessible through netprops or datamaps. The easiest solution in your case would be to simply force the player to call the "ChangeClass" function. We do this by force using the "class" console command.

Here is a simple plugin I whipped up so you can see how to change a client's class in Fortress-Forever.
PHP Code:
#include <sourcemod>
#include <sdktools_functions>

#pragma semicolon 1

new const String:PLUGIN_NAME[] = "Testing";
new const 
String:PLUGIN_VERSION[] = "1.0";

public 
Plugin:myinfo =
{
    
name PLUGIN_NAME,
    
author "hlstriker",
    
description "Testing.",
    
version PLUGIN_VERSION,
    
url "www.swoobles.com"
}

new const 
String:g_szClasses[][] =
{
    
"none",
    
"scout",
    
"sniper",
    
"soldier",
    
"demoman",
    
"medic",
    
"hwguy",
    
"pyro",
    
"spy",
    
"engineer",
    
"civilian"
};


public 
OnPluginStart()
{
    
RegConsoleCmd("sm_class"OnClass);
}

public 
Action:OnClass(iClientiArgs)
{
    if(!
iClient)
        return;
    
    if(!
iArgs)
    {
        
ReplyToCommand(iClient"Enter a class number 1-10.");
        return;
    }
    
    
decl String:szClass[3];
    
GetCmdArg(1szClasssizeof(szClass));
    
    new 
iClass StringToInt(szClass);
    if(
iClass || iClass 10)
    {
        
ReplyToCommand(iClient"Enter a class number 1-10.");
        return;
    }
    
    
ReplyToCommand(iClient"Current class: %s. New class: %s"g_szClasses[GetClassSlot(iClient)], g_szClasses[iClass]);
    
ForceChangeClass(iClientiClass);
}

GetClassSlot(iClient)
{
    return (
GetEntProp(iClientProp_Send"m_iClassStatus") & 0x0000000F);
}

// It would be nice if we could simply use SetClassForClient, but we must use ForceChangeClass instead.
// This is here just for an example.
stock SetClassForClient(iClientiSlot)
{
    
SetEntProp(iClientProp_Send"m_iClassStatus"iSlot 0x0000000F);
}

ForceChangeClass(iClientiClass)
{
    
// Make sure the team's class limits don't override the class we are trying to force to.
    
decl iOriginalClassLimit;
    new 
iTeamManager GetTeamManager(GetEntProp(iClientProp_Data"m_iTeamNum"));
    if(
iTeamManager)
    {
        
iOriginalClassLimit GetEntProp(iTeamManagerProp_Send"m_iClasses"_iClass);
        
SetEntProp(iTeamManagerProp_Send"m_iClasses"99_iClass);
    }
    
    
// Force the client to change their class and instantly respawn them on the next frame.
    
FakeClientCommand(iClient"class %s"g_szClasses[iClass]);
    
    
// Put the team's class limits back to normal.
    
if(iTeamManager)
        
SetEntProp(iTeamManagerProp_Send"m_iClasses"iOriginalClassLimit_iClass);
}

GetTeamManager(iTeam)
{
    static 
iTeamManagers[6], bool:bHasManagers;
    
    if(
iTeam >= sizeof(iTeamManagers))
        return 
0;
    
    if(!
bHasManagers)
    {
        
decl iTeamNum;
        new 
iEnt = -1;
        while((
iEnt FindEntityByClassname(iEnt"ff_team_manager")) != -1)
        {
            
iTeamNum GetEntProp(iEntProp_Send"m_iTeamNum");
            if(
iTeamNum >= sizeof(iTeamManagers))
                continue;
            
            
iTeamManagers[iTeamNum] = iEnt;
        }
        
        
bHasManagers true;
    }
    
    return 
iTeamManagers[iTeam];


Last edited by hlstriker; 11-28-2017 at 16:24.
hlstriker is offline
DarthMan
Veteran Member
Join Date: Aug 2011
Old 11-28-2017 , 06:08   Re: [H3LP] PlayerClass Fortress Forever
Reply With Quote #4

Quote:
Originally Posted by hlstriker View Post
You will want to use "m_iClassStatus".

GetClassSlot
PHP Code:
GetClassSlot(iClient)
{
    return (
GetEntProp(iClientProp_Send"m_iClassStatus") & 0x0000000F);

SetClassForClient
PHP Code:
SetClassForClient(iClientiSlot)
{
    
SetEntProp(iClientProp_Send"m_iClassStatus"iSlot 0x0000000F);

Unfortunately, it still doesn't change my class, but now there are no errors.
I also tested the GetClassSlot and that seems to work fine.

Last edited by DarthMan; 11-28-2017 at 06:45.
DarthMan is offline
hlstriker
Green Gaben
Join Date: Mar 2006
Location: OH-IO!
Old 11-28-2017 , 06:52   Re: [H3LP] PlayerClass Fortress Forever
Reply With Quote #5

Updated my post above.
hlstriker is offline
DarthMan
Veteran Member
Join Date: Aug 2011
Old 11-28-2017 , 08:12   Re: [H3LP] PlayerClass Fortress Forever
Reply With Quote #6

Quote:
Originally Posted by hlstriker View Post
You will want to use "m_iClassStatus". But that won't work to set the class, so read all to the end.

GetClassSlot
PHP Code:
GetClassSlot(iClient)
{
    return (
GetEntProp(iClientProp_Send"m_iClassStatus") & 0x0000000F);

SetClassForClient
PHP Code:
SetClassForClient(iClientiSlot)
{
    
SetEntProp(iClientProp_Send"m_iClassStatus"iSlot 0x0000000F);

However, because "m_iNextClass" is not changed the server will put you back to your original class. The variable "m_iNextClass" is what ultimately decides what class you will be when you respawn. The problem is "m_iNextClass" is not accessible through netprops or datamaps. The easiest solution in your case would be to simply force the player to call the "ChangeClass" function. We do this by force using the "class" console command.

Here is a simply plugin I whipped up so you can see how to change a client's class in Fortress-Forever.
PHP Code:
#include <sourcemod>
#include <sdktools_functions>

#pragma semicolon 1

new const String:PLUGIN_NAME[] = "Testing";
new const 
String:PLUGIN_VERSION[] = "1.0";

public 
Plugin:myinfo =
{
    
name PLUGIN_NAME,
    
author "hlstriker",
    
description "Testing.",
    
version PLUGIN_VERSION,
    
url "www.swoobles.com"
}

new const 
String:g_szClasses[][] =
{
    
"none",
    
"scout",
    
"sniper",
    
"soldier",
    
"demoman",
    
"medic",
    
"hwguy",
    
"pyro",
    
"spy",
    
"engineer",
    
"civilian"
};


public 
OnPluginStart()
{
    
RegConsoleCmd("sm_class"OnClass);
}

public 
Action:OnClass(iClientiArgs)
{
    if(!
iClient)
        return;
    
    if(!
iArgs)
    {
        
ReplyToCommand(iClient"Enter a class number 1-10.");
        return;
    }
    
    
decl String:szClass[3];
    
GetCmdArg(1szClasssizeof(szClass));
    
    new 
iClass StringToInt(szClass);
    if(
iClass || iClass 10)
    {
        
ReplyToCommand(iClient"Enter a class number 1-10.");
        return;
    }
    
    
ReplyToCommand(iClient"Current class: %s. New class: %s"g_szClasses[GetClassSlot(iClient)], g_szClasses[iClass]);
    
ForceChangeClass(iClientiClass);
}

GetClassSlot(iClient)
{
    return (
GetEntProp(iClientProp_Send"m_iClassStatus") & 0x0000000F);
}

// It would be nice if we could simply use SetClassForClient, but we must use ForceChangeClass instead.
// This is here just for an example.
stock SetClassForClient(iClientiSlot)
{
    
SetEntProp(iClientProp_Send"m_iClassStatus"iSlot 0x0000000F);
}

ForceChangeClass(iClientiClass)
{
    
// Make sure the team's class limits don't override the class we are trying to force to.
    
new Handle:hClassLimits CreateArray();
    new 
iTeamManager GetTeamManager(GetEntProp(iClientProp_Data"m_iTeamNum"));
    if(
iTeamManager)
    {
        new 
iArraySize GetEntPropArraySize(iTeamManagerProp_Send"m_iClasses");
        for(new 
i=0i<iArraySizei++)
        {
            
PushArrayCell(hClassLimitsGetEntProp(iTeamManagerProp_Send"m_iClasses"_i));
            
SetEntProp(iTeamManagerProp_Send"m_iClasses"0_i);
        }
    }
    
    
// Force the client to change their class and instantly respawn them on the next frame.
    
FakeClientCommand(iClient"class %s"g_szClasses[iClass]);
    
RequestFrame(RequestFrame_RespawnClientGetClientSerial(iClient));
    
    
// Put the team's class limits back to normal.
    
if(iTeamManager)
    {
        new 
iArraySize GetEntPropArraySize(iTeamManagerProp_Send"m_iClasses");
        for(new 
i=0i<iArraySizei++)
        {
            
SetEntProp(iTeamManagerProp_Send"m_iClasses"GetArrayCell(hClassLimitsi), _i);
        }
    }
    
    
CloseHandle(hClassLimits);
}

public 
RequestFrame_RespawnClient(any:iClientSerial)
{
    new 
iClient GetClientFromSerial(iClientSerial);
    if(!
iClient)
        return;
    
    
DispatchSpawn(iClient);
}

GetTeamManager(iTeam)
{
    static 
iTeamManagers[6], bool:bHasManagers;
    
    if(
iTeam >= sizeof(iTeamManagers))
        return 
0;
    
    if(!
bHasManagers)
    {
        
decl iTeamNum;
        new 
iEnt = -1;
        while((
iEnt FindEntityByClassname(iEnt"ff_team_manager")) != -1)
        {
            
iTeamNum GetEntProp(iEntProp_Send"m_iTeamNum");
            if(
iTeamNum >= sizeof(iTeamManagers))
                continue;
            
            
iTeamManagers[iTeamNum] = iEnt;
        }
        
        
bHasManagers true;
    }
    
    return 
iTeamManagers[iTeam];

When trying to spawn as a civilian, it says
#FF_ERROR_NOLONGERAVAILABLE.
DarthMan is offline
hlstriker
Green Gaben
Join Date: Mar 2006
Location: OH-IO!
Old 11-28-2017 , 15:26   Re: [H3LP] PlayerClass Fortress Forever
Reply With Quote #7

Quote:
Originally Posted by DarthMan View Post
When trying to spawn as a civilian, it says
#FF_ERROR_NOLONGERAVAILABLE.
What map was that on? Try removing RequestFrame() and putting DispatchSpawn() in its place.

Also change this line:
PHP Code:
SetEntProp(iTeamManagerProp_Send"m_iClasses"0_i); 
To this:
PHP Code:
SetEntProp(iTeamManagerProp_Send"m_iClasses"99_i); 

Last edited by hlstriker; 11-28-2017 at 15:29.
hlstriker is offline
Mitchell
~lick~
Join Date: Mar 2010
Old 11-28-2017 , 15:45   Re: [H3LP] PlayerClass Fortress Forever
Reply With Quote #8

Also instead of doing "GetEngineVersion()" within your stock you can just save it in a static variable or use HasEntProp()
__________________
Mitchell is offline
hlstriker
Green Gaben
Join Date: Mar 2006
Location: OH-IO!
Old 11-28-2017 , 16:04   Re: [H3LP] PlayerClass Fortress Forever
Reply With Quote #9

I went ahead and updated the ForceChangeClass function in my example plugin above. Although I would still like to know which map was giving you that message in console.
hlstriker is offline
DarthMan
Veteran Member
Join Date: Aug 2011
Old 11-28-2017 , 16:21   Re: [H3LP] PlayerClass Fortress Forever
Reply With Quote #10

Quote:
Originally Posted by hlstriker View Post
I went ahead and updated the ForceChangeClass function in my example plugin above. Although I would still like to know which map was giving you that message in console.
It was ff_monkey.
DarthMan is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 04:55.


Powered by vBulletin®
Copyright ©2000 - 2020, vBulletin Solutions, Inc.
Theme made by Freecode