So I see that alot of people like to uh.. make a command with a 0|1 option to toggle it on/off, and personally that's just inefficient for the user/admin.
Before I start: I want to say that this is generally what I like to do, as it might be a little extra work on my end, but it defiantly looks much nicer and refined.
Instead of using an argument to declare if we want to have, for instance, God Mode enabled, we can use a Global Variable.
This will be our FINISHED PRODUCT:
Spoiler
PHP Code:
#include <sourcemod>
#define pAuthor "EasSidezZ" #define pName "Toggle Command Tutorial" #define pDesc "A Tutorial to show how to toggle a command" #define pVersion "6.9" #define pURL "http://www.sourcemod.net"
/*Global Variables*/ new bool:g_bIsEnabled[MAXPLAYERS + 1]; /*Global Variables*/
public Plugin:myinfo = {name = pName, author = pAuthor, description = pDesc, version = pVersion, url = pURL}
public OnMapStart() { RegConsoleCmd("sm_godmode", command_GodMode, "- Toggle God Mode On and Off"); }
public OnClientPostAdminCheck(Client) { g_bIsEnabled[Client] = false; }
public OnClientDisconnect(Client) { g_bIsEnabled[Client] = false; }
//Toggle Godmode public Action:command_GodMode(Client, iArgs) { if(iArgs > 0) //If there are arguments, return an error. { ReplyToCommand(Client, "[SM] Invalid Usage: sm_godmode <NO ARGS>"); return Action:3; //Plugin Handled }
if(!g_bIsEnabled[Client]) //If the player does not have godmode, set godmode. { SetEntProp(Client, Prop_Data, "m_takedamage", 0, 1); g_bIsEnabled[Client] = true; ReplyToCommand(Client, "[SM] God Mode Enabled"); return Action:3; } else //If the player has godmode, remove it. { SetEntProp(Client, Prop_Data, "m_takedamage", 2, 1); g_bIsEnabled[Client] = false; ReplyToCommand(Client, "[SM] God Mode Disabled"); return Action:3; }
return Action:1; }
Here is an example of the OLD METHOD.
Spoiler
PHP Code:
#include <sourcemod>
#define pAuthor "EasSidezZ" #define pName "Toggle Command Tutorial" #define pDesc "A Tutorial to show how to toggle a command" #define pVersion "6.9" #define pURL "http://www.sourcemod.net"
/*Global Variables*/ new bool:g_bIsEnabled[MAXPLAYERS + 1]; /*Global Variables*/
public Plugin:myinfo = {name = pName, author = pAuthor, description = pDesc, version = pVersion, url = pURL}
public OnMapStart() { RegConsoleCmd("sm_godmode", command_GodMode, "- Toggle God Mode On and Off"); }
//Toggle Godmode public Action:command_GodMode(Client, iArgs) { decl String:sArg[32]; GetCmdArg(1, sArg, sizeof(sArg)); new iArg = StringToInt(sArg);
if(iArgs != 1) //If there are arguments, return an error. { ReplyToCommand(Client, "[SM] Invalid Usage: sm_godmode <NO ARGS>"); return Action:3; //Plugin Handled }
/*Alternate method for this... switch(iArg) { case 0: { SetEntProp(Client, Prop_Data, "m_takedamage", 2, 1); ReplyToCommand(Client, "[SM] God Mode Disabled"); return Action:3; }
case 1: { SetEntProp(Client, Prop_Data, "m_takedamage", 0, 1); ReplyToCommand(Client, "[SM] God Mode Enabled"); return Action:3; } } */
return Action:1; //Return Plugin_Changed }
I'm no master of sourcepawn, but I can tell you that there's really a ton wrong with this. For one, perhaps someone puts an argument value of 2? To fix this problem, we'll add a global client boolean, Implement our OnClientConnect()/OnClientPostAdminCheck() and OnClientDisconnect() and modify our godmode command slightly:
Spoiler
PHP Code:
#include <sourcemod>
#define pAuthor "EasSidezZ" #define pName "Toggle Command Tutorial" #define pDesc "A Tutorial to show how to toggle a command" #define pVersion "6.9" #define pURL "http://www.sourcemod.net"
/*Global Variables*/ new bool:g_bIsEnabled[MAXPLAYERS + 1]; /*Global Variables*/
public Plugin:myinfo = {name = pName, author = pAuthor, description = pDesc, version = pVersion, url = pURL}
public OnMapStart() { RegConsoleCmd("sm_godmode", command_GodMode, "- Toggle God Mode On and Off"); }
public OnClientPostAdminCheck(Client) { g_bIsEnabled[Client] = false; }
public OnClientDisconnect(Client) { g_bIsEnabled[Client] = false; }
//Toggle Godmode public Action:command_GodMode(Client, iArgs) { if(iArgs > 0) //If there are arguments, return an error. { ReplyToCommand(Client, "[SM] Invalid Usage: sm_godmode <NO ARGS>"); return Action:3; //Plugin Handled }
if(!g_bIsEnabled[Client]) //If the player does not have godmode, set godmode. { SetEntProp(Client, Prop_Data, "m_takedamage", 0, 1); g_bIsEnabled[Client] = true; ReplyToCommand(Client, "[SM] God Mode Enabled"); return Action:3; } else //If the player has godmode, remove it. { SetEntProp(Client, Prop_Data, "m_takedamage", 2, 1); g_bIsEnabled[Client] = false; ReplyToCommand(Client, "[SM] God Mode Disabled"); return Action:3; }
return Action:1; //We return Plugin_Changed because it will ALWAYS change, and we'll get a warning thrown if we don't return SOMETHING. }
As you can see, we've used our boolean to check and determine if the player has godmode. We also set it to 0 when they connect and disconnect because if we didn't, a player could leave and another would take their place, and this would assign the old client's value to the new client. (Pretty much, g_bIsEnabled[22].)
EXTRA NOTES:
Quote:
Originally Posted by ddhoward
Here's some more suggestions for making a command like this (that supports targeting other players)
Do CheckCommandAccess on an override similar to but different from the command name, such as "sm_godmode_admin" or "sm_godmode_targetothers" if your command was sm_godmode. If the player does not have access to that override (and/or no arguments exist), then ignore all arguments and simply toggle godmode on the using player, as you have done already in your code.
If the player has access to the override, and at least 1 argument has been given, run that first argument through ProcessTargetString.
If a second argument is not given, toggle godmode on all the given targets provided by ProcessTargetString. If a second argument WAS given, use the argument to determine if godmode should be toggled/enabled/disabled.
Something I learned in my time here is that the newer plugin developers are semi-braindead and require you to put everything in long terms, but yes your way would work I suppose, but it just looks alot weirder.. that and I just wanted to keep this as self-explanatory and basic as it could possibly get.
There are a few things I notice people doing:
Over/under validating clients.
Storing/passing entities or clients rather than using entrefs/serials/userids in delayed callbacks.
Using new instead of decl when the variable is going to be overwritten.
Disregarding return values of natives that have significant return values (usually bools, but also things like using isvalidentity instead of just checking for -1/INVALID_ENT_REFERENCE).
Making new variables before passing them to other functions, or using them in various statements (if, switch, etc), rather than just passing the return value.
Using servercommand, to change cvars or execute commands, rather than implementing the natives behind what needs to be done, or creating new natives to interface with related plugins.
Other stuff:
Using includes/stocks that don't really do anything other than add extra overhead for the mod they are working with.
Adding translation and config files to simple things that do not need them.
Annoying stuff:
Making code unreadable by using bad indentation, multiple file includes that don't make sense or are not necessary, or using inconsistent nesting (if / break / continue / return).
Reading in and constantly traversing a large file of keyvakues, rather than storing parts of them in a more optimized format for what you need, be it static vars/arrays, or tries/adt arrays.
Not using pragma semicolon.
__________________
Profile - Plugins
Add me on steam if you are seeking sp/map/model commissions.
There are a few things I notice people doing:
Over/under validating clients.
Storing/passing entities or clients rather than using entrefs/serials/userids in delayed callbacks.
Using new instead of decl when the variable is going to be overwritten.
Disregarding return values of natives that have significant return values (usually bools, but also things like using isvalidentity instead of just checking for -1/INVALID_ENT_REFERENCE).
Making new variables before passing them to other functions, or using them in various statements (if, switch, etc), rather than just passing the return value.
Using servercommand, to change cvars or execute commands, rather than implementing the natives behind what needs to be done, or creating new natives to interface with related plugins.
Other stuff:
Using includes/stocks that don't really do anything other than add extra overhead for the mod they are working with.
Adding translation and config files to simple things that do not need them.
Annoying stuff:
Making code unreadable by using bad indentation, multiple file includes that don't make sense or are not necessary, or using inconsistent nesting (if / break / continue / return).
Reading in and constantly traversing a large file of keyvakues, rather than storing parts of them in a more optimized format for what you need, be it static vars/arrays, or tries/adt arrays.
Not using pragma semicolon.
Half of that probably consists of my coding lmao xD
What i'm seeing more now days is people storing player data in enums. i would like to know the down fall of that, does that use up more memory per say?
_________________
Re-wrote the short plugin, i replaced alot. you dont really need #defines if you are only replacing one thing with them. Version should be the only #define, especially if you plan on releasing something like this it makes it easier to update the cvar and the plugin version at the same time.
Also you were doing a RegConsoleCmd on MapStart, im not entirely sure about this one, but im sure it's wrong, since you only need to do it on plugin start and unforseen things might happen with the code (like executing twice after a few map changes.)
Spoiler
Code:
new bool:g_bIsEnabled[MAXPLAYERS + 1] = {false,...};
#define pVersion "7.0"
public Plugin:myinfo = {
name = "Toggle Command Tutorial",
author = "EasSidezZ",
description = "A Tutorial to show how to toggle a command",
version = pVersion,
url = "http://www.sourcemod.net"
}
public OnPluginStart()
{
RegConsoleCmd("sm_godmode", command_GodMode, "- Toggle God Mode On and Off");
}
public OnClientDisconnect(Client)
{
g_bIsEnabled[Client] = false;
}
//Toggle Godmode
public Action:command_GodMode(Client, iArgs)
{
if(Client > 0 && IsClientInGame(Client)) {
g_bIsEnabled[Client] = !g_bIsEnabled[Client];
SetEntProp(Client, Prop_Data, "m_takedamage", (g_bIsEnabled[Client]) ? 0 : 2, 1);
ReplyToCommand(Client, "[SM] God Mode %s", (g_bIsEnabled[Client]) ? "Enabled" : "Disabled");
}
return Plugin_Handled;
}
There are a few things I notice people doing:
Over/under validating clients.
Storing/passing entities or clients rather than using entrefs/serials/userids in delayed callbacks.
Using new instead of decl when the variable is going to be overwritten.
Disregarding return values of natives that have significant return values (usually bools, but also things like using isvalidentity instead of just checking for -1/INVALID_ENT_REFERENCE).
Making new variables before passing them to other functions, or using them in various statements (if, switch, etc), rather than just passing the return value.
Using servercommand, to change cvars or execute commands, rather than implementing the natives behind what needs to be done, or creating new natives to interface with related plugins.
Other stuff:
Using includes/stocks that don't really do anything other than add extra overhead for the mod they are working with.
Adding translation and config files to simple things that do not need them.
Annoying stuff:
Making code unreadable by using bad indentation, multiple file includes that don't make sense or are not necessary, or using inconsistent nesting (if / break / continue / return).
Reading in and constantly traversing a large file of keyvakues, rather than storing parts of them in a more optimized format for what you need, be it static vars/arrays, or tries/adt arrays.
Not using pragma semicolon.
I didn't pragma semicolon for this, but defiantly what you're saying here is the efficiency clause of SP
Quote:
Originally Posted by Mitchell
Half of that probably consists of my coding lmao xD
What i'm seeing more now days is people storing player data in enums. i would like to know the down fall of that, does that use up more memory per say?
_________________
Re-wrote the short plugin, i replaced alot. you dont really need #defines if you are only replacing one thing with them. Version should be the only #define, especially if you plan on releasing something like this it makes it easier to update the cvar and the plugin version at the same time.
Also you were doing a RegConsoleCmd on MapStart, im not entirely sure about this one, but im sure it's wrong, since you only need to do it on plugin start and unforseen things might happen with the code (like executing twice after a few map changes.)
Spoiler
Code:
new bool:g_bIsEnabled[MAXPLAYERS + 1] = {false,...};
#define pVersion "7.0"
public Plugin:myinfo = {
name = "Toggle Command Tutorial",
author = "EasSidezZ",
description = "A Tutorial to show how to toggle a command",
version = pVersion,
url = "http://www.sourcemod.net"
}
public OnPluginStart()
{
RegConsoleCmd("sm_godmode", command_GodMode, "- Toggle God Mode On and Off");
}
public OnClientDisconnect(Client)
{
g_bIsEnabled[Client] = false;
}
//Toggle Godmode
public Action:command_GodMode(Client, iArgs)
{
if(Client > 0 && IsClientInGame(Client)) {
g_bIsEnabled[Client] = !g_bIsEnabled[Client];
SetEntProp(Client, Prop_Data, "m_takedamage", (g_bIsEnabled[Client]) ? 0 : 2, 1);
ReplyToCommand(Client, "[SM] God Mode %s", (g_bIsEnabled[Client]) ? "Enabled" : "Disabled");
}
return Plugin_Handled;
}
LOL I had NO idea I put it in MapStart, thanks for pointing that out. The if statement inside a single line thing just confuses me alot, so I'll stick to what I usually know
The if statement inside a single line thing just confuses me alot, so I'll stick to what I usually know
It's nice to get custom to, saves space when doing short things and could save time from copying and pasting.
These do the same thing. I like to use them in the cases of which i have to show a ON/OFF text in a print. I like having shorter code cause its easier to spot the bugs
either which way is right. it just comes down to personal preferences. although it would be better if you have a lot of functions you needed to check against a bool you would use the bracket statements.
This thread should be titled "How to PROPERLY make a self toggle command," as most commands would probably have some sort of admin targeting capability. Especially one that toggles godmode. And why return an error if arguments are provided? Why not just ignore the arguments?
Why are you using "Action" instead of "Plugin_Handled" ?
I like it more, I'm not sure why, that and I don't publish my plugins a whole lot, so I don't see the need. If it's proper conventions I'm fine with doing that
Quote:
Originally Posted by Mitchell
It's nice to get custom to, saves space when doing short things and could save time from copying and pasting.
These do the same thing. I like to use them in the cases of which i have to show a ON/OFF text in a print. I like having shorter code cause its easier to spot the bugs
either which way is right. it just comes down to personal preferences. although it would be better if you have a lot of functions you needed to check against a bool you would use the bracket statements.