├── .gitignore ├── hvh_essentials.sp ├── hvh_ff_nade_only.sp ├── hvh_public.sp └── hvh_weapon_selector.sp /.gitignore: -------------------------------------------------------------------------------- 1 | private 2 | -------------------------------------------------------------------------------- /hvh_essentials.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | ConVar um_restrict_untrusted_angles; 6 | ConVar um_restrict_body_lean; 7 | ConVar um_restrict_extended_angles; 8 | ConVar um_restrict_fake_duck; 9 | ConVar um_restrict_ax; 10 | 11 | ConVar um_rage_quit; 12 | ConVar um_reset_score; 13 | 14 | public Plugin:myinfo = 15 | { 16 | name = "unmatched.gg HvH Essentials", 17 | author = "imi-tat0r", 18 | description = "Core functionality for HvH servers", 19 | version = "2.0" 20 | }; 21 | 22 | public void OnPluginStart() 23 | { 24 | // setup cvars 25 | um_restrict_untrusted_angles = CreateConVar("um_restrict_untrusted_angles", "1", "If this cvar is enabled, untrusted angles will be normalized/clamped", FCVAR_NOTIFY | FCVAR_REPLICATED); 26 | um_restrict_body_lean = CreateConVar("um_restrict_body_lean", "1", "If this cvar is enabled, body lean will be disabled", FCVAR_NOTIFY | FCVAR_REPLICATED); 27 | um_restrict_extended_angles = CreateConVar("um_restrict_extended_angles", "1", "If this cvar is enabled, extended angles will be disabled", FCVAR_NOTIFY | FCVAR_REPLICATED); 28 | um_restrict_fake_duck = CreateConVar("um_restrict_fake_duck", "0", "If this cvar is enabled, fake duck will be disabled", FCVAR_NOTIFY | FCVAR_REPLICATED); 29 | um_restrict_ax = CreateConVar("um_restrict_ax", "1", "If this cvar is enabled, AX will be disabled", FCVAR_NOTIFY | FCVAR_REPLICATED); 30 | 31 | um_rage_quit = CreateConVar("um_rage_quit", "1", "If this cvar is enabled, rage quit is enabled", FCVAR_NOTIFY | FCVAR_REPLICATED); 32 | um_reset_score = CreateConVar("um_reset_score", "1", "If this cvar is enabled, reset score is enabled", FCVAR_NOTIFY | FCVAR_REPLICATED); 33 | 34 | ServerCommand("mp_backup_round_file \"\""); 35 | ServerCommand("mp_backup_round_file_last \"\""); 36 | ServerCommand("mp_backup_round_file_pattern \"\""); 37 | ServerCommand("mp_backup_round_auto 0"); 38 | 39 | RegConsoleCmd("rq", Command_RageQuit); 40 | RegConsoleCmd("ragequit", Command_RageQuit); 41 | 42 | RegConsoleCmd("rs", Command_ResetScore); 43 | RegConsoleCmd("resetscore", Command_ResetScore); 44 | } 45 | 46 | public void OnMapStart() 47 | { 48 | ServerCommand("mp_backup_round_file \"\""); 49 | ServerCommand("mp_backup_round_file_last \"\""); 50 | ServerCommand("mp_backup_round_file_pattern \"\""); 51 | ServerCommand("mp_backup_round_auto 0"); 52 | } 53 | 54 | public Action Command_RageQuit(int client, int args) 55 | { 56 | // feature disabled 57 | if (!GetConVarBool(um_rage_quit)) 58 | return Plugin_Handled; 59 | 60 | // invalid client 61 | if (!IsValidClient(client)) 62 | return Plugin_Handled; 63 | 64 | // get client name 65 | char name[MAX_NAME_LENGTH]; 66 | GetClientName(client, name, sizeof(name)); 67 | 68 | // public shame 69 | PrintToChatAll("[unmatched.\x10gg\x01] \x04%s\x01 just rage quit.", name) 70 | 71 | // kick message 72 | KickClient(client, "Rage quit!"); 73 | return Plugin_Handled; 74 | } 75 | 76 | public Action Command_ResetScore(int client, int args) 77 | { 78 | // feature disabled 79 | if (!GetConVarBool(um_reset_score)) 80 | return Plugin_Handled; 81 | 82 | // invalid client 83 | if (!IsValidClient(client)) 84 | return Plugin_Handled; 85 | 86 | // get client name 87 | char name[MAX_NAME_LENGTH]; 88 | GetClientName(client, name, sizeof(name)); 89 | 90 | // check if already 0 91 | if(GetClientDeaths(client) == 0 && GetClientFrags(client) == 0 && CS_GetClientAssists(client) == 0 && CS_GetMVPCount(client) == 0) 92 | { 93 | PrintToChat(client, "[unmatched.\x10gg\x01] Your score already is 0.") 94 | return Plugin_Continue; 95 | } 96 | 97 | // reset stats 98 | SetEntProp(client, Prop_Data, "m_iFrags", 0); 99 | SetEntProp(client, Prop_Data, "m_iDeaths", 0); 100 | CS_SetMVPCount(client, 0); 101 | CS_SetClientAssists(client, 0); 102 | CS_SetClientContributionScore(client, 0); 103 | 104 | // public shame 105 | PrintToChatAll("[unmatched.\x10gg\x01] Player \x04%s\x01 just reset their score.", name) 106 | return Plugin_Handled; 107 | } 108 | 109 | 110 | public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon, &subtype, &cmdnum, &tickcount, &seed, mouse[2]) 111 | { 112 | // player is dead, continue 113 | new bool:alive = IsPlayerAlive(client); 114 | if(!alive) 115 | return Plugin_Continue; 116 | 117 | // ax fix 118 | if (GetConVarBool(um_restrict_ax)) 119 | { 120 | if (!GetEntProp(client, Prop_Data, "m_bLagCompensation")) 121 | SetEntProp(client, Prop_Data, "m_bLagCompensation", 1); 122 | } 123 | 124 | // fake duck fix 125 | if (GetConVarBool(um_restrict_fake_duck)) 126 | { 127 | if( buttons & IN_BULLRUSH ) 128 | buttons &= ~IN_BULLRUSH; 129 | } 130 | 131 | // untrusted angles fix 132 | if (GetConVarBool(um_restrict_untrusted_angles)) 133 | { 134 | // pitch clamp 135 | if (angles[0] > 89.0) 136 | angles[0] = 89.0; 137 | else if (angles[0] < -89.0) 138 | angles[0] = -89.0; 139 | 140 | // yaw clamp 141 | if (angles[1] > 180.0) 142 | angles[1] = 180.0; 143 | if(angles[1] < -180.0) 144 | angles[1] = -180.0; 145 | 146 | // roll clamp 147 | if (angles[2] > 90.0) 148 | angles[2] = 90.0; 149 | else if (angles[2] < -90.0) 150 | angles[2] = -90.0; 151 | } 152 | 153 | // roll disable 154 | if (GetConVarBool(um_restrict_body_lean)) 155 | { 156 | if(angles[2] != 0.0) 157 | angles[2] = 0.0; 158 | } 159 | 160 | return Plugin_Changed; 161 | } 162 | 163 | // primordial fix - credits: https://github.com/r4klatif/extended-angle-fix 164 | public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2]) 165 | { 166 | if (!GetConVarBool(um_restrict_extended_angles)) 167 | return; 168 | 169 | float eye_angles[3]; 170 | float v_angle[3]; 171 | 172 | GetEntPropVector(client, Prop_Data, "v_angle", v_angle); 173 | 174 | eye_angles[0] = GetEntPropFloat(client, Prop_Send, "m_angEyeAngles[0]"); 175 | eye_angles[1] = GetEntPropFloat(client, Prop_Send, "m_angEyeAngles[1]"); 176 | eye_angles[2] = v_angle[2]; 177 | 178 | SetEntPropVector(client, Prop_Data, "v_angle", eye_angles); 179 | } 180 | 181 | stock bool IsValidClient(int client) 182 | { 183 | if(client <= 0 ) return false; 184 | if(client > MaxClients) return false; 185 | if(!IsClientConnected(client)) return false; 186 | return IsClientInGame(client); 187 | } -------------------------------------------------------------------------------- /hvh_ff_nade_only.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | public Plugin myinfo = 6 | { 7 | name = "unmatched.gg Friendly Fire settings", 8 | author = "imi-tat0r", 9 | description = "Manage the damage of friendly fire.", 10 | version = "1.2", 11 | }; 12 | 13 | ConVar um_friendlyfire_utility; 14 | ConVar um_friendlyfire_weapon; 15 | 16 | public void OnPluginStart() 17 | { 18 | um_friendlyfire_utility = CreateConVar("um_friendlyfire_utility", "1", "If this cvar is enabled, friendly utility will deal damage", FCVAR_NOTIFY | FCVAR_REPLICATED); 19 | um_friendlyfire_weapon = CreateConVar("um_friendlyfire_weapon", "1", "If this cvar is enabled, friendly fire will deal damage", FCVAR_NOTIFY | FCVAR_REPLICATED); 20 | 21 | for (int i = 1; i <= MaxClients; i++) 22 | if (IsClientInGame(i)) 23 | OnClientPutInServer(i); 24 | } 25 | 26 | public void OnConfigsExecuted() 27 | { 28 | SetConVar("ff_damage_reduction_grenade", "1"); 29 | SetConVar("ff_damage_reduction_grenade_self", "1"); 30 | SetConVar("ff_damage_reduction_other", "1"); 31 | } 32 | 33 | public void OnClientPutInServer(int client) 34 | { 35 | SDKHook(client, SDKHook_TraceAttack, SDK_OnTraceAttack); 36 | SDKHook(client, SDKHook_OnTakeDamage, SDK_OnTakeDamage); 37 | } 38 | 39 | public Action SDK_OnTraceAttack(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &ammotype, int hitbox, int hitgroup) 40 | { 41 | if (!IsClientInGame(victim) || 42 | !IsEntityClient(attacker) || 43 | !IsClientInGame(attacker) || 44 | GetClientTeam(attacker) != GetClientTeam(victim)) 45 | return Plugin_Continue; 46 | 47 | if (!GetConVarBool(um_friendlyfire_weapon) && 48 | (view_as(damagetype & DMG_BULLET) || 49 | view_as(damagetype & DMG_SLASH) || 50 | view_as(damagetype & DMG_SHOCK))) { 51 | damage = 0.0; 52 | return Plugin_Changed; 53 | } 54 | 55 | if (!GetConVarBool(um_friendlyfire_utility) && 56 | (view_as(damagetype & DMG_BURN) || 57 | view_as(damagetype & DMG_BLAST))) { 58 | damage = 0.0; 59 | return Plugin_Changed; 60 | } 61 | 62 | return Plugin_Continue; 63 | } 64 | 65 | public Action SDK_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3]) 66 | { 67 | if (!IsClientInGame(victim) || 68 | !IsEntityClient(attacker) || 69 | !IsClientInGame(attacker) || 70 | IsEntityClient(inflictor) || 71 | GetClientTeam(attacker) != GetClientTeam(victim) || 72 | GetConVarBool(um_friendlyfire_utility)) 73 | return Plugin_Continue; 74 | 75 | 76 | char classname[256]; 77 | GetEntityClassname(inflictor, classname, sizeof(classname)); 78 | 79 | if (StrEqual(classname, "inferno", true)) 80 | { 81 | if (attacker != victim) 82 | { 83 | damage = 0.0; 84 | return Plugin_Changed; 85 | } 86 | } 87 | 88 | return Plugin_Continue; 89 | } 90 | 91 | void SetConVar(const char[] cvarName, const char[] value) 92 | { 93 | ConVar cvar = FindConVar(cvarName); 94 | if (cvar) 95 | cvar.SetString(value); 96 | } 97 | 98 | bool IsEntityClient(int client) 99 | { 100 | return (client > 0 && client <= MaxClients); 101 | } -------------------------------------------------------------------------------- /hvh_public.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | ConVar um_rage_quit; 5 | ConVar um_reset_score; 6 | 7 | public Plugin:myinfo = 8 | { 9 | name = "unmatched.gg HvH Public", 10 | author = "imi-tat0r", 11 | description = "Core functionality for unmatched.gg public servers", 12 | version = "1.0" 13 | }; 14 | 15 | public void OnPluginStart() 16 | { 17 | um_rage_quit = CreateConVar("um_rage_quit", "1", "If this cvar is enabled, rage quit is enabled", FCVAR_NOTIFY | FCVAR_REPLICATED); 18 | um_reset_score = CreateConVar("um_reset_score", "1", "If this cvar is enabled, reset score is enabled", FCVAR_NOTIFY | FCVAR_REPLICATED); 19 | 20 | ServerCommand("mp_backup_round_file \"\""); 21 | ServerCommand("mp_backup_round_file_last \"\""); 22 | ServerCommand("mp_backup_round_file_pattern \"\""); 23 | ServerCommand("mp_backup_round_auto 0"); 24 | 25 | RegConsoleCmd("rq", Command_RageQuit); 26 | RegConsoleCmd("ragequit", Command_RageQuit); 27 | 28 | RegConsoleCmd("rs", Command_ResetScore); 29 | RegConsoleCmd("resetscore", Command_ResetScore); 30 | } 31 | 32 | public void OnMapStart() 33 | { 34 | ServerCommand("mp_backup_round_file \"\""); 35 | ServerCommand("mp_backup_round_file_last \"\""); 36 | ServerCommand("mp_backup_round_file_pattern \"\""); 37 | ServerCommand("mp_backup_round_auto 0"); 38 | } 39 | 40 | public Action Command_RageQuit(int client, int args) 41 | { 42 | // feature disabled 43 | if (!GetConVarBool(um_rage_quit)) 44 | return Plugin_Handled; 45 | 46 | // invalid client 47 | if (!IsValidClient(client)) 48 | return Plugin_Handled; 49 | 50 | // get client name 51 | char name[MAX_NAME_LENGTH]; 52 | GetClientName(client, name, sizeof(name)); 53 | 54 | // public shame 55 | PrintToChatAll("[unmatched.\x10gg\x01] \x04%s\x01 just rage quit.", name) 56 | 57 | // kick message 58 | KickClient(client, "Rage quit!"); 59 | return Plugin_Handled; 60 | } 61 | 62 | public Action Command_ResetScore(int client, int args) 63 | { 64 | // feature disabled 65 | if (!GetConVarBool(um_reset_score)) 66 | return Plugin_Handled; 67 | 68 | // invalid client 69 | if (!IsValidClient(client)) 70 | return Plugin_Handled; 71 | 72 | // get client name 73 | char name[MAX_NAME_LENGTH]; 74 | GetClientName(client, name, sizeof(name)); 75 | 76 | // check if already 0 77 | if(GetClientDeaths(client) == 0 && GetClientFrags(client) == 0 && CS_GetClientAssists(client) == 0 && CS_GetMVPCount(client) == 0) 78 | { 79 | PrintToChat(client, "[unmatched.\x10gg\x01] Your score already is 0.") 80 | return Plugin_Continue; 81 | } 82 | 83 | // reset stats 84 | SetEntProp(client, Prop_Data, "m_iFrags", 0); 85 | SetEntProp(client, Prop_Data, "m_iDeaths", 0); 86 | CS_SetMVPCount(client, 0); 87 | CS_SetClientAssists(client, 0); 88 | CS_SetClientContributionScore(client, 0); 89 | 90 | // public shame 91 | PrintToChatAll("[unmatched.\x10gg\x01] Player \x04%s\x01 just reset their score.", name) 92 | return Plugin_Handled; 93 | } 94 | 95 | stock bool IsValidClient(int client) 96 | { 97 | if(client <= 0 ) return false; 98 | if(client > MaxClients) return false; 99 | if(!IsClientConnected(client)) return false; 100 | return IsClientInGame(client); 101 | } -------------------------------------------------------------------------------- /hvh_weapon_selector.sp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | bool um_lateload = false; 6 | 7 | public Plugin:myinfo = 8 | { 9 | name = "unmatched.gg Weapon Selector", 10 | author = "imi-tat0r", 11 | description = "Allows players to set a preference for weapons after CS:GO inventory services got shut down.", 12 | version = "v1.0.2" 13 | }; 14 | 15 | bool g_bPrefersR8[MAXPLAYERS + 1] = {false}; 16 | bool g_bPrefersUSP[MAXPLAYERS + 1] = {false}; 17 | bool g_bPrefersCZ[MAXPLAYERS + 1] = {false}; 18 | int g_iPlayerNotified[MAXPLAYERS + 1] = {0}; 19 | int r8Price = 600; 20 | int deaglePrice = 700; 21 | int p2000UspPrice = 200; 22 | int czTecPrice = 500; 23 | 24 | 25 | public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) 26 | { 27 | um_lateload = late; 28 | return APLRes_Success; 29 | } 30 | 31 | public void OnPluginStart() 32 | { 33 | RegConsoleCmd("deagle", Command_Deagle); 34 | RegConsoleCmd("r8", Command_Revolver); 35 | RegConsoleCmd("revolver", Command_Revolver); 36 | 37 | RegConsoleCmd("usp", Command_USP); 38 | RegConsoleCmd("p2000", Command_P2000); 39 | RegConsoleCmd("p2k", Command_P2000); 40 | 41 | RegConsoleCmd("cz", Command_CZ); 42 | RegConsoleCmd("tec", Command_NotCZ); 43 | RegConsoleCmd("tec9", Command_NotCZ); 44 | RegConsoleCmd("fiveseven", Command_NotCZ); 45 | RegConsoleCmd("57", Command_NotCZ); 46 | 47 | HookEvent("player_spawn", Player_Spawn); 48 | } 49 | 50 | public void OnClientConnected(int client) 51 | { 52 | ResetUserPreference(client); 53 | } 54 | 55 | public void OnClientDisconnect(int client) 56 | { 57 | ResetUserPreference(client); 58 | } 59 | 60 | void Player_Spawn(Event event, const char[] name, bool dB) 61 | { 62 | CreateTimer(0.1, HandleSpawn, event.GetInt("userid")); 63 | } 64 | 65 | public Action HandleSpawn(Handle timer, any userId) 66 | { 67 | int client = GetClientOfUserId(view_as(userId)); 68 | if (!client) 69 | return Plugin_Stop; 70 | 71 | if (GetClientTeam(client) <= CS_TEAM_SPECTATOR) 72 | return Plugin_Stop; 73 | 74 | if (g_iPlayerNotified[client] >= 1) 75 | return Plugin_Stop; 76 | 77 | PrintToChat(client, "[unmatched.\x10gg\x01] Use \x10!deagle\x01 or \x10!r8\x01 at any time to set your preference."); 78 | PrintToChat(client, "[unmatched.\x10gg\x01] Use \x10!p2000\x01 or \x10!usp\x01 at any time to set your preference."); 79 | PrintToChat(client, "[unmatched.\x10gg\x01] Use \x10!tec9\x01/\x10!fiveseven\x01 or \x10!cz\x01 at any time to set your preference."); 80 | 81 | if (g_bPrefersR8[client]) 82 | PrintToChat(client, "[unmatched.\x10gg\x01] Current preference: \x10R8 Revolver"); 83 | else 84 | PrintToChat(client, "[unmatched.\x10gg\x01] Current preference: \x10Desert Eagle"); 85 | 86 | if (g_bPrefersUSP[client]) 87 | PrintToChat(client, "[unmatched.\x10gg\x01] Current preference: \x10USP-S"); 88 | else 89 | PrintToChat(client, "[unmatched.\x10gg\x01] Current preference: \x10P2000"); 90 | 91 | if (g_bPrefersCZ[client]) 92 | PrintToChat(client, "[unmatched.\x10gg\x01] Current preference: \x10CZ75-Auto"); 93 | else 94 | PrintToChat(client, "[unmatched.\x10gg\x01] Current preference: \x10Tec-9/Five-Seven"); 95 | 96 | g_iPlayerNotified[client]++; 97 | 98 | return Plugin_Stop; 99 | } 100 | 101 | public Action Command_Deagle(int client, int args) 102 | { 103 | return Command_Handler("deagle", client, args); 104 | } 105 | 106 | public Action Command_Revolver(int client, int args) 107 | { 108 | return Command_Handler("r8", client, args); 109 | } 110 | 111 | public Action Command_USP(int client, int args) 112 | { 113 | return Command_Handler("usp", client, args); 114 | } 115 | 116 | public Action Command_P2000(int client, int args) 117 | { 118 | return Command_Handler("p2000", client, args); 119 | } 120 | 121 | public Action Command_CZ(int client, int args) 122 | { 123 | return Command_Handler("cz", client, args); 124 | } 125 | 126 | public Action Command_NotCZ(int client, int args) 127 | { 128 | return Command_Handler("tec9", client, args); 129 | } 130 | 131 | public Action Command_Handler(const char[] command, int client, int args) 132 | { 133 | if (args > 1) 134 | { 135 | char com[128] = "[unmatched.\x10gg\x01] Usage: !"; 136 | StrCat(com, sizeof(com), command); 137 | 138 | ReplyToCommand(client, com); 139 | return Plugin_Handled; 140 | } 141 | 142 | char weapon[32] = ""; 143 | 144 | if (StrEqual(command, "deagle")) 145 | { 146 | g_bPrefersR8[client] = false; 147 | weapon = "Desert Eagle"; 148 | } 149 | else if (StrEqual(command, "r8")) 150 | { 151 | g_bPrefersR8[client] = true; 152 | weapon = "R8 Revolver"; 153 | } 154 | else if (StrEqual(command, "p2000")) 155 | { 156 | g_bPrefersUSP[client] = false; 157 | weapon = "P2000"; 158 | } 159 | else if (StrEqual(command, "usp")) 160 | { 161 | g_bPrefersUSP[client] = true; 162 | weapon = "USP-S"; 163 | } 164 | else if (StrEqual(command, "cz")) 165 | { 166 | g_bPrefersCZ[client] = true; 167 | weapon = "CZ75-Auto"; 168 | } 169 | else 170 | { 171 | g_bPrefersCZ[client] = false; 172 | weapon = "Tec-9/Five-Seven"; 173 | } 174 | 175 | char com[128] = "[unmatched.\x10gg\x01] Current preference: \x10"; 176 | StrCat(com, sizeof(com), weapon); 177 | ReplyToCommand(client, com); 178 | 179 | return Plugin_Handled; 180 | } 181 | 182 | public Action CS_OnBuyCommand(int client, const char [] szWeapon) 183 | { 184 | if(!IsClientInGame(client) || !IsPlayerAlive(client) || GetEntProp(client, Prop_Send, "m_bInBuyZone") == 0) 185 | return Plugin_Continue; 186 | 187 | if(GetClientTeam(client) <= CS_TEAM_SPECTATOR) 188 | return Plugin_Continue; 189 | 190 | char str[128] = "weapon_"; 191 | StrCat(str, sizeof(str), szWeapon); 192 | 193 | if (StrEqual(str, "weapon_deagle")) 194 | return HandleBuyEvent(client, "weapon_revolver", r8Price, g_bPrefersR8[client]); 195 | else if (StrEqual(str, "weapon_revolver")) 196 | return HandleBuyEvent(client, "weapon_deagle", deaglePrice, !g_bPrefersR8[client]); 197 | else if (StrEqual(str, "weapon_hkp2000")) 198 | return HandleBuyEvent(client, "weapon_usp_silencer", p2000UspPrice, g_bPrefersUSP[client]); 199 | else if (StrEqual(str, "weapon_usp_silencer")) 200 | return HandleBuyEvent(client, "weapon_hkp2000", p2000UspPrice, !g_bPrefersUSP[client]); 201 | else if (StrEqual(str, "weapon_tec9") || StrEqual(str, "weapon_fiveseven")) 202 | return HandleBuyEvent(client, "weapon_cz75a", czTecPrice, g_bPrefersCZ[client]); 203 | else if (StrEqual(str, "weapon_cz75a")) 204 | { 205 | if (GetClientTeam(client) == CS_TEAM_T) 206 | return HandleBuyEvent(client, "weapon_tec9", czTecPrice, !g_bPrefersCZ[client]); 207 | else 208 | return HandleBuyEvent(client, "weapon_fiveseven", czTecPrice, !g_bPrefersCZ[client]); 209 | } 210 | else 211 | return Plugin_Continue; 212 | } 213 | 214 | public Action CS_OnGetWeaponPrice(int client, const char[] weapon, int& price) 215 | { 216 | // only deagle and r8 differ in price 217 | if (StrEqual(weapon, "weapon_deagle") || StrEqual(weapon, "weapon_revolver")) 218 | { 219 | price = g_bPrefersR8[client] ? r8Price : deaglePrice; 220 | return Plugin_Handled; 221 | } 222 | 223 | return Plugin_Continue; 224 | } 225 | 226 | public Action HandleBuyEvent(int client, const char[] weapon_replace, int price_replace, bool prefers) 227 | { 228 | PrintToConsole(client, "HandleBuyEvent: %s, %d, %d", weapon_replace, price_replace, prefers); 229 | 230 | if (!prefers) 231 | return Plugin_Continue; 232 | 233 | // can we afford the weapon? 234 | int money = GetClientMoney(client); 235 | if (money < price_replace) 236 | return Plugin_Handled; 237 | // if player already has the weapon, do nothing 238 | else if (HasPlayerWeapon(client, weapon_replace)) 239 | return Plugin_Handled; 240 | else 241 | { 242 | DropSecondary(client); 243 | SetClientMoney(client, money - price_replace); 244 | GivePlayerItem(client, weapon_replace); 245 | 246 | return Plugin_Handled; 247 | } 248 | } 249 | 250 | public bool HasPlayerWeapon(int client, const char[] weapon) 251 | { 252 | int m_hMyWeapons = FindSendPropInfo("CBasePlayer", "m_hMyWeapons"); 253 | if(m_hMyWeapons == -1) 254 | return false; 255 | 256 | for(int offset = 0; offset < 128; offset += 4) 257 | { 258 | int weap = GetEntDataEnt2(client, m_hMyWeapons+offset); 259 | 260 | if(IsValidEdict(weap)) 261 | { 262 | char classname[32]; 263 | GetWeaponClassname(weap, -1, classname, 32); 264 | 265 | if(StrEqual(classname, weapon)) 266 | return true; 267 | } 268 | } 269 | 270 | return false; 271 | } 272 | 273 | public void DropSecondary(int client) 274 | { 275 | int slot2 = GetPlayerWeaponSlot(client, 1) 276 | 277 | if (slot2 != -1) 278 | { 279 | CS_DropWeapon(client, slot2, false); 280 | } 281 | } 282 | 283 | public int GetClientMoney(int client) 284 | { 285 | return GetEntProp(client, Prop_Send, "m_iAccount"); 286 | } 287 | 288 | public void SetClientMoney(int client, int money) 289 | { 290 | SetEntProp(client, Prop_Send, "m_iAccount", money); 291 | } 292 | 293 | public void OnMapStart() 294 | { 295 | for (int i = 1; i <= MaxClients; i++) 296 | ResetUserPreference(i); 297 | } 298 | 299 | void ResetUserPreference(int client) 300 | { 301 | g_bPrefersR8[client] = false; 302 | g_bPrefersUSP[client] = false; 303 | g_bPrefersCZ[client] = false; 304 | g_iPlayerNotified[client] = false; 305 | } 306 | 307 | stock void GetWeaponClassname(int weapon, int index = -1, char[] classname, int maxLen) 308 | { 309 | GetEdictClassname(weapon, classname, maxLen); 310 | 311 | if(index == -1) 312 | index = GetEntProp(weapon, Prop_Send, "m_iItemDefinitionIndex"); 313 | 314 | switch(index) 315 | { 316 | case 60: strcopy(classname, maxLen, "weapon_m4a1_silencer"); 317 | case 61: strcopy(classname, maxLen, "weapon_usp_silencer"); 318 | case 63: strcopy(classname, maxLen, "weapon_cz75a"); 319 | case 64: strcopy(classname, maxLen, "weapon_revolver"); 320 | } 321 | } --------------------------------------------------------------------------------