AlliedModders Donor
|
02-13-2015
, 15:01
[TF2] Sourcemod-Hammer Integration - Keypad Doors
|
#1
|
Hello there!
A brief explanation of what I'm working on: - Have a keypad-protected doors on the map,
- Have a player being able to enter a password,
- A plugin checks if the password matches the correct one,
- Opens the doors if it does.
Everything is working quite correctly. I'm just looking for a way to improve this and make it as perfect as it can get with the help from you, guys.
Also, I really wanna share this.
THE TEST MAP
There are quite a few entities which the plugin is accessing: - 10 keypad func_buttons:
- Named "num_0", "num_1", "num_2", ..., "num_9".
- The OnPressed output is being triggered by damage.
- 8 symbol func_brushes:
- Named "symb_0", "symb_1", "symb_2", ..., "symb_7".
- They play the role of the "●" symbols which are being displayed when typing in a password.
- They are being displayed on a "screen" next to the keypad made of func_details.
- They are being enabled/disabled by the plugin so as to show/hide them.
- 1 "OK" func_button:
- Named simply "ok".
- It plays the role of the "Submit" button when finished typing a password, just like Enter.
- 1 door func_door_rotating:
- Named simply "doors".
- The door entity which is being triggered when the password is correct, duh...
THE PLUGIN
CVar: sm_door_pass changes the password. Default is "0000".
PHP Code:
#pragma semicolon 1
#include <sourcemod> #include <sdktools>
//Holds the 0-8 characters password new Handle:Keypad_Password = INVALID_HANDLE;
//These variables hold the entities new buttons[10]; //Numpad button new butt_ok; //The "OK" button new doors; //and the doors
new symbols[8]; //Symbols which are being displayed on the screen (func_brush enabling, disabling) new bool:symbools[8]; //symbools is there to know whether a symbol is being displayed
//Current password which is being entered new String:curPass[9];
public Plugin:myinfo = { name = "Keypad Password Check", author = "Phil25", description = "Checks if a player has entered the right password on the map's keypad and opens the doors.", };
public OnPluginStart(){ Keypad_Password = CreateConVar( "sm_door_pass", //Name of the CVar "0000", //Default Value "The password which protects the doors", //Description FCVAR_PROTECTED //Flag ); RegConsoleCmd("sm_printdebug", Command_PrintDebug); //Used for testing purposes
}
public OnMapStart(){ /* ASSIGNING ALL THE ENTITIES TO THEIR RESPECTIVE VARIABLES */ //Assuming there's more than one doors on the map: new ent_doors = -1; while((ent_doors = FindEntityByClassname(ent_doors, "func_door_rotating")) != INVALID_ENT_REFERENCE){ decl String:ent_doors_name[32]; GetEntPropString(ent_doors, Prop_Data, "m_iName", ent_doors_name, sizeof(ent_doors_name)); if(StrEqual(ent_doors_name, "doors")) doors = ent_doors; } //Searching for numpad buttons: (They are named: "num_0", "num_1", "num_2" and so on...) new ent_butt = -1; while((ent_butt = FindEntityByClassname(ent_butt, "func_button")) != INVALID_ENT_REFERENCE){ //Looping through every valid func_button decl String:butt_name[32]; GetEntPropString(ent_butt, Prop_Data, "m_iName", butt_name, sizeof(butt_name)); //Getting the name of current one if(StrEqual(butt_name, "ok")) //Check if the entity's name equals the "ok" button butt_ok = ent_butt; else{ //If not then look for numpad buttons decl String:exp_butt_name[2][16]; //Checking, if exploding the name using "_" will return more strings: if(ExplodeString(butt_name, "_", exp_butt_name, sizeof(exp_butt_name), sizeof(exp_butt_name[])) > 0) if(StrEqual(exp_butt_name[0], "num")) //If yes, check if the first part equals "num" buttons[StringToInt(exp_butt_name[1])] = ent_butt; //If also yes, assign the ent_butt to its corresponding array id in buttons[] using the second part } } //Checking for symbols to display on the keypad's screen: (Named: "symb_0", "symb_1", "symb_2" and so on...) //(Those are kinda optional, they're just there to give the person who's putting the code in some feedback) new ent_symb = -1; while((ent_symb = FindEntityByClassname(ent_symb, "func_brush")) != INVALID_ENT_REFERENCE){ decl String:symb_name[32]; //Everything here follows the same rule as above GetEntPropString(ent_symb, Prop_Data, "m_iName", symb_name, sizeof(symb_name)); decl String:exp_symb_name[2][16]; if(ExplodeString(symb_name, "_", exp_symb_name, sizeof(exp_symb_name), sizeof(exp_symb_name[])) > 0) if(StrEqual(exp_symb_name[0], "symb")) symbols[StringToInt(exp_symb_name[1])] = ent_symb; } /* HOOKING "OnPressed" OUTPUTS OF THE BUTTONS */ for(new i = 0; i < sizeof(buttons); i++){ HookSingleEntityOutput(buttons[i], "OnPressed", ButtonPressedNum); } HookSingleEntityOutput(butt_ok, "OnPressed", ButtonPressedOk); }
public ButtonPressedNum(const String:output[], caller, activator, Float:delay){ /*AcceptEntityInput(doors, "Open", activator, -1); decl String:temp_name[32]; GetEntPropString(caller, Prop_Data, "m_iName", temp_name, sizeof(temp_name)); //Used to test, figured I'll decl String:acti_name[32]; //leave the code for now. GetClientName(activator, acti_name, sizeof(acti_name)); //(Tests successful ofc :p) PrintToChatAll( "Output Name: %s, Ent Name: %s, Activator: %s (client: %d), Delay: %0.2f", output, temp_name, acti_name, activator, delay );*/ decl String:caller_name[32]; GetEntPropString(caller, Prop_Data, "m_iName", caller_name, sizeof(caller_name)); //Get the button's name decl String:add_str[2][16]; ExplodeString(caller_name, "_", add_str, sizeof(add_str), sizeof(add_str[])); //Get the button number Format(curPass, sizeof(curPass), "%s%s", curPass, add_str[1]); //Add the strings together //Loop through the symbols and enable the next one which hasn't been enabled yet for(new i = 0; i < sizeof(symbools); i++){ if(!symbools[i]){ AcceptEntityInput(symbols[i], "Enable", activator, -1); symbools[i] = true; break; //If found a one which hasn't been enabled, enable it and break the loop }else continue; //If not, keep searching } }
public ButtonPressedOk(const String:output[], caller, activator, Float:delay){ decl String:correctPass[9]; //Get the correct pass from the ConVar GetConVarString(Keypad_Password, correctPass, sizeof(correctPass)); if(StrEqual(curPass, correctPass)){ //Check if the strings match decl String:activ_name[64]; GetClientName(activator, activ_name, sizeof(activ_name)); PrintToChat(activator, "\x01Password \x077ee12dCorrect\x01! Welcome, \x04%s\x01!", activ_name); AcceptEntityInput(doors, "Open", activator, -1); //Open the door entity if yep }else PrintToChat(activator, "\x01Password \x07d72833Incorrect\x01!"); //Yell at the guy if nah Format(curPass, sizeof(curPass), ""); //Set the current password which is being entered to nothing for(new i = 0; i < sizeof(symbools); i++){ AcceptEntityInput(symbols[i], "Disable", activator, -1); //Disable every symbol symbools[i] = false; //Set every symbool to false } }
public Action:Command_PrintDebug(client, args){ PrintToConsole(client, ""); PrintToConsole(client, "------------------"); PrintToConsole(client, " - SYMBOLS:"); for(new i = 0; i < sizeof(symbols); i++){ decl String:ent_name[32]; GetEntPropString(symbols[i], Prop_Data, "m_iName", ent_name, sizeof(ent_name)); PrintToConsole(client, "%d. %s", i, ent_name); } PrintToConsole(client, ""); PrintToConsole(client, " - BUTTONS:"); for(new i = 0; i < sizeof(buttons); i++){ decl String:ent_name[32]; GetEntPropString(buttons[i], Prop_Data, "m_iName", ent_name, sizeof(ent_name)); PrintToConsole(client, "%d. %s", i, ent_name); } decl String:butt_name[32]; GetEntPropString(butt_ok, Prop_Data, "m_iName", butt_name, sizeof(butt_name)); PrintToConsole(client, "10. %s", butt_name); PrintToConsole(client, ""); PrintToConsole(client, " - REST:"); decl String:door_name[32]; GetEntPropString(doors, Prop_Data, "m_iName", door_name, sizeof(door_name)); PrintToConsole(client, "Doors: %s", door_name); PrintToConsole(client, "------------------"); PrintToConsole(client, ""); PrintToChat(client, "Check the console for output."); }
STUFF WORTH NOTICING- The plugin needs to be reloaded for it to work for some reason.
- The symbols in Hammer are round although they appear as squares in the game.
- The OnPressed in buttons is activated via damage. When you use explosives in order to do that symbols display in an incorrect matter.
- To push the buttons you should get a pistol or something small and shoot them from a small distance because the melee registering system in TF2 is weird at some angles...
QUESTIONS- About the plugin not working from start, what is up with that??
- I'm fetching a lot of entities, is there any better way of doing that other than what I'm using?
- Are the plugin's while loops supposed to break when finding the right entity?
- Treating buttons with explosives. What can be done so they won't break the symbols?
- For Hammer folks: Is there a way of making the symbols appear after one another using some logic system in the editor? They just need to be turned on/off and the "OK" button can simply clear them all out.
- Is there a better way of doing what I'm trying to achieve? What is your opinion?
I'm looking forward to discuss any additional comments on the topic. Thank you all very much in advance and take care.
ATTACHMENTS
Map BSP File (Game-Ready)
Map VMF File (Hammer Source)
Last edited by Phil25; 02-14-2015 at 03:11.
|
|