├── .hgignore ├── README.md ├── SMDJ Web Interface ├── admin.php ├── black.css ├── config.php ├── counter-strike.css ├── default.css ├── footer.php ├── header.php ├── help.php ├── index.php ├── player_mp3_maxi.swf ├── player_mp3_multi.swf ├── playlist.php ├── shuffle.php ├── tf2.css ├── tf2build.eot ├── tf2build.ttf ├── tf2secondary.eot └── tf2secondary.ttf ├── SMDJ_Web_Interface.zip ├── anticapslock.txt ├── anyteleporter.txt ├── arena_reloaded.txt ├── automatic_steam_update.txt ├── backpack-tf.txt ├── backpack_viewer.txt ├── botmanager-names.txt ├── botmanager-randomdifficulty.txt ├── botmanager.txt ├── chatcolors.txt ├── chatcolorsclantagmodule.txt ├── chatcolorsdistinguishmodule.txt ├── chatcolorsmysqlmodule.txt ├── chatcolorstogglemodule.txt ├── citybans.txt ├── configs └── custom-chatcolors.cfg ├── connect_method.txt ├── convarfaker.txt ├── data └── backpack_viewer.txt ├── endless_ctf.txt ├── enhanced_items.txt ├── game_desc_override.txt ├── gamedata ├── arena-reloaded.games.txt └── detect_os.games.txt ├── humiliationconditions.txt ├── humiliationglow.txt ├── itemserver.txt ├── kartify.txt ├── motd_text_http.txt ├── mutecheck.txt ├── namechange_fix.txt ├── namelock.txt ├── no_enemy_in_spawn.txt ├── player_analytics.txt ├── plugins ├── anticapslock.smx ├── anyteleporter.smx ├── arena_reloaded.smx ├── auto_steam_update.smx ├── backpack-tf.smx ├── backpack_viewer.smx ├── botmanager-names.smx ├── botmanager-randomdifficulty.smx ├── botmanager.smx ├── citybans.smx ├── connect_method.smx ├── convarfaker.smx ├── custom-chatcolors-clantag.smx ├── custom-chatcolors-distinguish.smx ├── custom-chatcolors-mysql.smx ├── custom-chatcolors-toggle.smx ├── custom-chatcolors.smx ├── endless_ctf.smx ├── enhanced_items.smx ├── humiliationconditions.smx ├── humiliationglow.smx ├── itemserver.smx ├── kartify.smx ├── motd_text_http.smx ├── mutecheck.smx ├── namechange_fix.smx ├── namelock.smx ├── no_enemy_in_spawn.smx ├── player_analytics.smx ├── rainbowize.smx ├── really_no_weapons.smx ├── short_circuit_nerf.smx ├── shutdowncountdown.smx ├── smac_autodemo.smx ├── smdj.smx ├── st_gamedesc_override.smx ├── steamrep_checker.smx ├── sticky_jumper_bombz.smx ├── teamscores.smx ├── tidykick.smx ├── unrestricted_fov.smx ├── votekick_switcher.smx └── votescramble.smx ├── rainbowize.txt ├── really_no_weapons.txt ├── scripting ├── anticapslock.sp ├── anyteleporter.sp ├── arena_reloaded.sp ├── auto_steam_update.sp ├── backpack-tf.sp ├── backpack_viewer.sp ├── botmanager-names.sp ├── botmanager-randomdifficulty.sp ├── botmanager.sp ├── citybans.sp ├── connect_method.sp ├── convarfaker.sp ├── custom-chatcolors-clantag.sp ├── custom-chatcolors-distinguish.sp ├── custom-chatcolors-mysql.sp ├── custom-chatcolors-toggle.sp ├── custom-chatcolors.sp ├── endless_ctf.sp ├── enhanced_items.sp ├── humiliationconditions.sp ├── humiliationglow.sp ├── include │ ├── advanced_motd.inc │ ├── botmanager.inc │ ├── bytebuffer.inc │ ├── ccc.inc │ ├── morecolors.inc │ ├── player_analytics.inc │ ├── smdj.inc │ └── tidykick.inc ├── itemserver.sp ├── kartify.sp ├── mckayupdater.sp ├── motd_text_http.sp ├── mutecheck.sp ├── namechange_fix.sp ├── namelock.sp ├── no_enemy_in_spawn.sp ├── player_analytics.sp ├── rainbowize.sp ├── really_no_weapons.sp ├── short_circuit_nerf.sp ├── shutdowncountdown.sp ├── smac_autodemo.sp ├── smdj.sp ├── st_gamedesc_override.sp ├── steamrep_checker.sp ├── sticky_jumper_bombz.sp ├── teamscores.sp ├── tidykick.sp ├── unrestricted_fov.sp ├── votekick_switcher.sp └── votescramble.sp ├── short_circuit_nerf.txt ├── shutdowncountdown.txt ├── smac-autodemo.txt ├── smdj_version.txt ├── steamrep.txt ├── sticky_jumper_bombz.txt ├── teamscores.txt ├── tidykick.txt ├── translations ├── backpack-tf.phrases.txt ├── da │ └── backpack-tf.phrases.txt ├── de │ └── backpack-tf.phrases.txt ├── es │ └── backpack-tf.phrases.txt ├── nl │ └── backpack-tf.phrases.txt ├── pl │ └── backpack-tf.phrases.txt └── ru │ └── backpack-tf.phrases.txt ├── unrestricted_fov.txt ├── votekick_switcher.txt └── votescramble.txt /.hgignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/.hgignore -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Public SourceMod Plugins 2 | 3 | This repository contains all of the SourceMod plugins that I have [publicly released](http://www.doctormckay.com/projects.php). 4 | 5 | * [SourceMod](http://www.sourcemod.net) 6 | * [AlliedModders](https://forums.alliedmods.net) -------------------------------------------------------------------------------- /SMDJ Web Interface/admin.php: -------------------------------------------------------------------------------- 1 | Incorrect password specified.
'; } 11 | echo 'Please provide your password below.

'; 12 | echo '
'; 13 | echo '
'; 14 | echo ''; 15 | echo '
'; 16 | require('./footer.php'); 17 | exit; 18 | } 19 | if(isset($_GET['upload'])) { 20 | require('./header.php'); 21 | if($_GET['error'] == 1) { echo '
The song title is required.
'; } 22 | if($_GET['error'] == 2) { echo '
Filetype must be MP3 (given ' . $_GET['type'] . ')
'; } 23 | if($_GET['error'] == 3) { echo '
Unable to connect to the FTP server.
'; } 24 | if($_GET['error'] == 4) { echo '
Unable to upload the file to the FTP server.
'; } 25 | if($_GET['errorcode']) { echo '
There was an error while uploading the file. Error code: ' . $_GET['errorcode'] . '
'; } 26 | echo '

Upload A Song

'; 27 | echo '
'; 28 | echo ''; 29 | echo ''; 30 | echo ''; 31 | echo ''; 32 | echo '
Title:
File:


'; 33 | echo ''; 34 | echo '


'; 35 | echo 'Back To Management'; 36 | require('./footer.php'); 37 | exit; 38 | } 39 | if(isset($_GET['deleteall'])) { 40 | require('./header.php'); 41 | echo '

Delete All Songs

'; 42 | echo 'WARNING! You are about to nuke your database! All your songs will be permanently cleared.

'; 43 | echo 'If you understand what you are doing and want to continue, click the "NUKE!" button below. Otherwise, click the Return link.

'; 44 | echo '
'; 45 | echo ''; 46 | echo '

'; 47 | echo 'Return'; 48 | require('./footer.php'); 49 | exit; 50 | } 51 | if($_POST['nuke']) { 52 | mysql_query('TRUNCATE TABLE `smdj_songs`'); 53 | header('location: admin.php'); 54 | exit; 55 | } 56 | if($_POST['submit']) { 57 | if($_POST['do'] == 'upload') { 58 | if(empty($_POST['title'])) { 59 | header('location: admin.php?upload&error=1'); 60 | exit; 61 | } 62 | if($_FILES['file']['error'] > 0) { 63 | header('location: admin.php?upload&errorcode=' . $_FILES['file']['error']); 64 | exit; 65 | } 66 | if($_FILES['file']['type'] != 'audio/mp3' && $_FILES['file']['type'] != 'audio/mpeg') { 67 | header('location: admin.php?upload&error=2&type=' . urlencode($_FILES['file']['type'])); 68 | exit; 69 | } 70 | if($uploadmethod == 'local') { 71 | move_uploaded_file($_FILES['file']['tmp_name'], './music/' . $_FILES['file']['name']); 72 | $url = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; 73 | $url = substr($url, 0, strlen($url) - 10); 74 | $url = $url . '/music/' . $_FILES['file']['name']; 75 | } 76 | if($uploadmethod == 'ftp') { 77 | $ftpcon = ftp_connect($ftp['host']); 78 | $login = ftp_login($ftpcon, $ftp['user'], $ftp['pass']); 79 | if(!$ftpcon || !$login) { 80 | header('location: admin.php?upload&error=3'); 81 | exit; 82 | } 83 | $upload = ftp_put($ftpcon, $ftp['path'] . '/' . $_FILES['file']['name'], $_FILES['file']['tmp_name'], FTP_BINARY); 84 | if(!$upload) { 85 | header('location: admin.php?upload&error=1'); 86 | exit; 87 | } 88 | ftp_close($ftpcon); 89 | $url = 'http://' . $ftp['http'] . '/' . $_FILES['file']['name']; 90 | } 91 | $q = mysql_fetch_array(mysql_query("SELECT * FROM `smdj_songs` ORDER BY id DESC")); 92 | $id = ++$q['id']; 93 | mysql_query("INSERT INTO `smdj_songs` (id, title, url) VALUES ('$id', '" . mysql_real_escape_string($_POST['title']) . "', '$url')"); 94 | header('location: admin.php?done=1'); 95 | exit; 96 | } elseif($_POST['do'] == 'add') { 97 | if(empty($_POST['title']) || empty($_POST['url'])) { 98 | header('location: admin.php?error=1'); 99 | exit; 100 | } 101 | $q = mysql_fetch_array(mysql_query("SELECT * FROM `smdj_songs` ORDER BY id DESC")); 102 | $id = ++$q['id']; 103 | mysql_query("INSERT INTO `smdj_songs` (id, title, url) VALUES ('$id', '" . mysql_real_escape_string($_POST['title']) . "', '" . mysql_real_escape_string($_POST['url']) . "')"); 104 | header('location: admin.php?done=1'); 105 | exit; 106 | } elseif($_POST['do'] == 'modify') { 107 | if(empty($_POST['title']) || empty($_POST['url'])) { 108 | header('location: admin.php?error=1&id=' . $_POST['id']); 109 | exit; 110 | } 111 | mysql_query("UPDATE `smdj_songs` SET title = '" . mysql_real_escape_string($_POST['title']) . "', url = '" . mysql_real_escape_string($_POST['url']) . "' WHERE id = '" . mysql_real_escape_string($_POST['id']) . "'"); 112 | header('location: admin.php?done=2'); 113 | exit; 114 | } elseif($_POST['delete']) { 115 | mysql_query("DELETE FROM `smdj_songs` WHERE id = '" . mysql_real_escape_string($_POST['delete']) . "'"); 116 | header('location: admin.php?done=3'); 117 | exit; 118 | } 119 | } 120 | require('./header.php'); 121 | if($_GET['error'] == 1) { echo '
The song title and MP3 URL are required.
'; } 122 | if($_GET['done'] == 1) { echo '
The song has been added.
'; } 123 | if($_GET['done'] == 2) { echo '
The song has been updated.
'; } 124 | if($_GET['done'] == 3) { echo '
The song has been deleted.
'; } 125 | $version_check = file_get_contents('https://bitbucket.org/Doctor_McKay/public-plugins/raw/default/smdj_version.txt'); 126 | if($version_check !== false && $version_check != SMDJ_VERSION) echo '
The SMDJ Web Interface is out-of-date. You are running v' . SMDJ_VERSION . ', and the most recent version is v' . $version_check . '

'; 127 | if($_GET['id']) { 128 | if(!mysql_num_rows($query = mysql_query("SELECT * FROM `smdj_songs` WHERE id = '" . mysql_real_escape_string($_GET['id']) . "'"))) { 129 | echo 'Invalid song ID!'; 130 | } else { 131 | $query = mysql_fetch_array($query); 132 | echo '

' . $query['title'] . '

'; 133 | echo '
'; 134 | echo ''; 135 | echo ''; 136 | echo ''; 137 | echo ''; 138 | echo ''; 139 | echo '
Song Title:
MP3 URL:
'; 140 | echo '

'; 141 | echo '
'; 142 | echo 'Be sure to include the protocol (i.e. http://) in the URL!

'; 143 | echo '
'; 144 | echo ''; 145 | echo ''; 146 | echo '


'; 147 | echo 'Return To Song List'; 148 | } 149 | } else { 150 | echo ''; 151 | echo ''; 152 | echo ''; 153 | echo '
Plugin Config Variables:
smdj_auth_token"' . md5(sha1($config['pass'])) . '"
smdj_url"http://' . $_SERVER['HTTP_HOST'] . str_replace('/admin.php', '', $_SERVER['SCRIPT_NAME']) . '"
'; 154 | echo '

Edit A Song

'; 155 | $query = mysql_query("SELECT * FROM `smdj_songs` ORDER BY title ASC"); 156 | while($arr = mysql_fetch_array($query)) { 157 | echo '' . $arr['title'] . '
'; 158 | } 159 | echo '

Add A Song

'; 160 | echo 'Upload A Song
'; 161 | echo '
'; 162 | echo ''; 163 | echo ''; 164 | echo ''; 165 | echo ''; 166 | echo '
Song Title:
MP3 URL:
'; 167 | echo '

'; 168 | echo '
'; 169 | echo 'Be sure to include the protocol (i.e. http://) in the URL!

'; 170 | echo 'Return To Front-End

'; 171 | echo 'Delete All Songs

'; 172 | } 173 | require('./footer.php'); 174 | ?> -------------------------------------------------------------------------------- /SMDJ Web Interface/black.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | body { 4 | font-family:Verdana, Arial, sans-serif; 5 | font-size:14px; 6 | text-align:center; 7 | background-color:#000000; 8 | color:#FFFFFF; 9 | } 10 | 11 | div#footer { 12 | font-size:10px; 13 | margin-top:40px; 14 | } 15 | 16 | a { 17 | color:#FFFFFF; 18 | text-decoration:underline; 19 | } 20 | 21 | a:hover { 22 | text-decoration:none; 23 | } 24 | 25 | a:active { 26 | text-decoration:underline; 27 | } 28 | 29 | table { 30 | margin:auto; 31 | } 32 | 33 | td { 34 | text-align:left; 35 | } 36 | 37 | th { 38 | font-family:Verdana, Arial, sans-serif; 39 | font-weight:bold; 40 | } 41 | 42 | .success { 43 | width:90%; 44 | font-weight:bold; 45 | border:2px solid #00FF00; 46 | border-radius:10px; 47 | padding:5px; 48 | margin:auto; 49 | } 50 | 51 | .error { 52 | width:90%; 53 | font-weight:bold; 54 | border:2px solid #FF0000; 55 | border-radius:10px; 56 | padding:5px; 57 | margin:auto; 58 | } 59 | 60 | .right { 61 | text-align:right; 62 | } -------------------------------------------------------------------------------- /SMDJ Web Interface/config.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /SMDJ Web Interface/counter-strike.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | body { 4 | font-family:Calibri, Candara, Segoe, Geneva, Tahoma, Arial, sans-serif; 5 | font-size:14px; 6 | text-align:center; 7 | background-color:#003300; 8 | color:#FFFFFF; 9 | } 10 | 11 | div#footer { 12 | font-size:10px; 13 | margin-top:40px; 14 | } 15 | 16 | a { 17 | color:#FFFFFF; 18 | text-decoration:underline; 19 | } 20 | 21 | a:hover { 22 | text-decoration:none; 23 | } 24 | 25 | a:active { 26 | text-decoration:underline; 27 | } 28 | 29 | table { 30 | margin:auto; 31 | } 32 | 33 | td { 34 | text-align:left; 35 | } 36 | 37 | th { 38 | font-family:Calibri, Candara, Segoe, Geneva, Tahoma, Arial, sans-serif; 39 | font-weight:bold; 40 | } 41 | 42 | .success { 43 | width:90%; 44 | font-weight:bold; 45 | border:2px solid #00FF00; 46 | border-radius:10px; 47 | padding:5px; 48 | margin:auto; 49 | } 50 | 51 | .error { 52 | width:90%; 53 | font-weight:bold; 54 | border:2px solid #FF0000; 55 | border-radius:10px; 56 | padding:5px; 57 | margin:auto; 58 | } 59 | 60 | .right { 61 | text-align:right; 62 | } -------------------------------------------------------------------------------- /SMDJ Web Interface/default.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | body { 4 | font-family:Verdana, Arial; 5 | font-size:14px; 6 | text-align:center; 7 | } 8 | 9 | div#footer { 10 | color:#666666; 11 | font-size:10px; 12 | margin-top:40px; 13 | } 14 | 15 | table { 16 | margin:auto; 17 | } 18 | 19 | td { 20 | text-align:left; 21 | } 22 | 23 | th { 24 | font-family:Verdana, Arial, sans-serif; 25 | font-weight:bold; 26 | } 27 | 28 | .success { 29 | width:90%; 30 | font-weight:bold; 31 | border:2px solid #00FF00; 32 | border-radius:10px; 33 | padding:5px; 34 | margin:auto; 35 | } 36 | 37 | .error { 38 | width:90%; 39 | font-weight:bold; 40 | border:2px solid #FF0000; 41 | border-radius:10px; 42 | padding:5px; 43 | margin:auto; 44 | } 45 | 46 | .right { 47 | text-align:right; 48 | } -------------------------------------------------------------------------------- /SMDJ Web Interface/footer.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /SMDJ Web Interface/header.php: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | SourceMod DJ 11 | 12 | 13 | 14 |

SourceMod DJ

15 | -------------------------------------------------------------------------------- /SMDJ Web Interface/help.php: -------------------------------------------------------------------------------- 1 | 6 |

Adobe Flash Player Help

7 | Please visit this page in your desktop Web browser: http://

8 |

How to install Adobe Flash Player for Other Browsers

9 | First, go to this URL: http://get.adobe.com/flashplayer/otherversions/
10 | In Step 1, select your computer's operating system.
11 | In Step 2, select Flash Player (version) for Other Browsers.
12 | Be sure to uncheck any software you don't want, then click Download.
13 | After you install Flash (you may need to reboot), SMDJ should work correctly.

14 | If you can see and use the music player below and are currently viewing this page from in-game, then SMDJ will work for you:

15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /SMDJ Web Interface/index.php: -------------------------------------------------------------------------------- 1 | = 10 && $_GET['volume'] <= 200) { 52 | $volume = $_GET['volume']; 53 | } else { 54 | $volume = 100; 55 | } 56 | echo '

' . $query['title'] . '

'; 57 | echo ' 58 | 59 | 60 | '; 61 | echo '

'; 62 | echo 'Song Selection'; 63 | } else { 64 | echo 'Shuffle All

'; 65 | if(isset($_GET['repeat'])) { 66 | if($_GET['repeat']) { 67 | $loop = '&repeat=1'; 68 | } else { 69 | $loop = '&repeat=0'; 70 | } 71 | } else { 72 | $loop = ''; 73 | } 74 | $query = mysql_query("SELECT * FROM `smdj_songs` ORDER BY title ASC"); 75 | while($arr = mysql_fetch_array($query)) { 76 | echo '' . $arr['title'] . '
'; 77 | } 78 | echo '

'; 79 | echo 'Administration'; 80 | } 81 | require('./footer.php'); 82 | ?> -------------------------------------------------------------------------------- /SMDJ Web Interface/player_mp3_maxi.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/SMDJ Web Interface/player_mp3_maxi.swf -------------------------------------------------------------------------------- /SMDJ Web Interface/player_mp3_multi.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/SMDJ Web Interface/player_mp3_multi.swf -------------------------------------------------------------------------------- /SMDJ Web Interface/playlist.php: -------------------------------------------------------------------------------- 1 | = 1 && $_POST['method'] <= 3) { 4 | header('Content-type: text/plain'); 5 | if($_POST['auth'] != md5(sha1($config['pass']))) { 6 | die('Bad auth token'); 7 | } 8 | if($_POST['method'] == 1) { // adding 9 | if(!$_POST['name'] || !$_POST['steamid'] || !$_POST['songs']) { 10 | die('Invalid data'); 11 | } 12 | $q = mysql_fetch_array(mysql_query("SELECT * FROM `smdj_playlists` ORDER BY id DESC")); 13 | $id = $q['id'] + 1; 14 | $name = mysql_real_escape_string($_POST['name']); 15 | $steamid = mysql_real_escape_string($_POST['steamid']); 16 | $songs = mysql_real_escape_string($_POST['songs']); 17 | $name = str_replace('"', '', $name); 18 | if(mysql_num_rows(mysql_query("SELECT * FROM `smdj_playlists` WHERE steamid = '$steamid' AND name = '$name'"))) { 19 | die('Already exists'); 20 | } 21 | mysql_query("INSERT INTO `smdj_playlists` (id, name, steamid, songs) VALUES ('$id', '$name', '$steamid', '$songs')"); 22 | exit; 23 | } elseif($_POST['method'] == 2) { // deleting 24 | if(!$_POST['id']) { 25 | die('Invalid data'); 26 | } 27 | mysql_query("DELETE FROM `smdj_playlists` WHERE id = '" . mysql_real_escape_string($_POST['id']) . "'"); 28 | } 29 | } 30 | if(!$_GET['id']) { 31 | header('location: index.php'); 32 | exit; 33 | } 34 | $q = mysql_fetch_array(mysql_query("SELECT * FROM `smdj_playlists` WHERE id = '" . mysql_real_escape_string($_GET['id']) . "'")); 35 | if(!$q['id']) { 36 | header('location: index.php'); 37 | exit; 38 | } 39 | if(isset($_GET['getlist'])) { 40 | header('Content-type: text/plain'); 41 | $songs = explode(',', $q['songs']); 42 | if($_GET['shuffle']) { 43 | shuffle($songs); 44 | } 45 | foreach($songs as $value) { 46 | $info = mysql_fetch_array(mysql_query("SELECT * FROM `smdj_songs` WHERE id = '$value'")); 47 | if(!$info['title']) { 48 | continue; 49 | } 50 | echo $info['url'] . '|' . $info['title'] . "\n"; 51 | } 52 | exit; 53 | } 54 | require('./header.php'); 55 | if(isset($_GET['volume']) && $_GET['volume'] >= 10 && $_GET['volume'] <= 200) { 56 | $volume = $_GET['volume']; 57 | } else { 58 | $volume = 100; 59 | } 60 | ?> 61 |

62 | 63 | 64 | 65 |

66 | Song Selection 67 | -------------------------------------------------------------------------------- /SMDJ Web Interface/shuffle.php: -------------------------------------------------------------------------------- 1 | 20 |

Shuffle All

21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SMDJ Web Interface/tf2.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | @font-face { 4 | font-family:TF2Build; 5 | src: url("tf2build.eot"); 6 | src: local("TF2Build"), url("tf2build.ttf") format("truetype"); 7 | } 8 | 9 | @font-face { 10 | font-family:TF2Secondary; 11 | src: url("tf2secondary.eot"); 12 | src: local("TF2Secondary"), url("tf2secondary.ttf") format("truetype"); 13 | } 14 | 15 | body { 16 | font-family:TF2Secondary, Verdana, Arial; 17 | font-size:14px; 18 | text-align:center; 19 | background-color:#393431; 20 | color:#EBE2CA; 21 | } 22 | 23 | h1, h2 { 24 | font-family:TF2Build, Verdana, Arial; 25 | } 26 | 27 | div#footer { 28 | color:#666666; 29 | font-family:TF2Build, Verdana, Arial; 30 | font-size:10px; 31 | margin-top:40px; 32 | } 33 | 34 | a { 35 | color:#EBE2CA; 36 | } 37 | 38 | a:hover { 39 | color:#FF0000; 40 | } 41 | 42 | a:active { 43 | color:#DD0000; 44 | } 45 | 46 | table { 47 | margin:auto; 48 | } 49 | 50 | td { 51 | text-align:left; 52 | } 53 | 54 | th { 55 | font-family:TF2Build, Verdana, Arial, sans-serif; 56 | font-weight:bold; 57 | } 58 | 59 | .success { 60 | font-family:TF2Build, Verdana, Arial; 61 | width:90%; 62 | border:2px solid #00FF00; 63 | border-radius:10px; 64 | padding:5px; 65 | margin:auto; 66 | } 67 | 68 | .error { 69 | font-family:TF2Build, Verdana, Arial; 70 | width:90%; 71 | border:2px solid #FF0000; 72 | border-radius:10px; 73 | padding:5px; 74 | margin:auto; 75 | } 76 | 77 | .right { 78 | text-align:right; 79 | } -------------------------------------------------------------------------------- /SMDJ Web Interface/tf2build.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/SMDJ Web Interface/tf2build.eot -------------------------------------------------------------------------------- /SMDJ Web Interface/tf2build.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/SMDJ Web Interface/tf2build.ttf -------------------------------------------------------------------------------- /SMDJ Web Interface/tf2secondary.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/SMDJ Web Interface/tf2secondary.eot -------------------------------------------------------------------------------- /SMDJ Web Interface/tf2secondary.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/SMDJ Web Interface/tf2secondary.ttf -------------------------------------------------------------------------------- /SMDJ_Web_Interface.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/SMDJ_Web_Interface.zip -------------------------------------------------------------------------------- /anticapslock.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.1.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Added admin immunity" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/anticapslock.smx" 17 | "Source" "Path_SM/scripting/anticapslock.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /anyteleporter.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.3.1" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Removed duplicate version cvar, cleaned up some stuff" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/anyteleporter.smx" 17 | "Source" "Path_SM/scripting/anyteleporter.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /arena_reloaded.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.0.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Initial release" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/arena_reloaded.smx" 17 | "Plugin" "Path_SM/gamedata/arena-reloaded.games.txt" 18 | "Source" "Path_SM/scripting/arena_reloaded.sp" 19 | "Source" "Path_SM/scripting/mckayupdater.sp" 20 | } 21 | } -------------------------------------------------------------------------------- /automatic_steam_update.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.9.1" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Updater improvements" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/auto_steam_update.smx" 17 | "Source" "Path_SM/scripting/auto_steam_update.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /backpack-tf.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "2.11.1" 8 | "Previous" "2.11.0" 9 | } 10 | 11 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 12 | "Notes" " - Added Uncraftable Haunted quality" 13 | } 14 | 15 | "Files" 16 | { 17 | "Patch" 18 | { 19 | "Plugin" "Path_SM/plugins/backpack-tf.smx" 20 | "Source" "Path_SM/scripting/backpack-tf.sp" 21 | } 22 | 23 | "Plugin" "Path_SM/plugins/backpack-tf.smx" 24 | "Plugin" "Path_SM/translations/backpack-tf.phrases.txt" 25 | "Plugin" "Path_SM/translations/pl/backpack-tf.phrases.txt" 26 | "Plugin" "Path_SM/translations/da/backpack-tf.phrases.txt" 27 | "Plugin" "Path_SM/translations/nl/backpack-tf.phrases.txt" 28 | "Plugin" "Path_SM/translations/es/backpack-tf.phrases.txt" 29 | "Plugin" "Path_SM/translations/de/backpack-tf.phrases.txt" 30 | "Plugin" "Path_SM/translations/ru/backpack-tf.phrases.txt" 31 | 32 | "Source" "Path_SM/scripting/backpack-tf.sp" 33 | "Source" "Path_SM/scripting/mckayupdater.sp" 34 | "Source" "Path_SM/scripting/include/advanced_motd.inc" 35 | } 36 | } -------------------------------------------------------------------------------- /backpack_viewer.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.1.3" 8 | "Previous" "1.1.2" 9 | } 10 | 11 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 12 | "Notes" " - Changed default viewer to backpacktf" 13 | } 14 | 15 | "Files" 16 | { 17 | "Patch" 18 | { 19 | "Plugin" "Path_SM/plugins/backpack_viewer.smx" 20 | "Plugin" "Path_SM/data/backpack_viewer.txt" 21 | "Source" "Path_SM/scripting/backpack_viewer.sp" 22 | } 23 | 24 | "Plugin" "Path_SM/plugins/backpack_viewer.smx" 25 | "Plugin" "Path_SM/data/backpack_viewer.txt" 26 | 27 | "Source" "Path_SM/scripting/backpack_viewer.sp" 28 | "Source" "Path_SM/scripting/mckayupdater.sp" 29 | "Source" "Path_SM/scripting/include/advanced_motd.inc" 30 | } 31 | } -------------------------------------------------------------------------------- /botmanager-names.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.0.0" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Initial release" 11 | } 12 | 13 | "Files" 14 | { 15 | "Plugin" "Path_SM/plugins/botmanager-names.smx" 16 | "Source" "Path_SM/scripting/botmanager-names.sp" 17 | } 18 | } -------------------------------------------------------------------------------- /botmanager-randomdifficulty.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.0.0" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Initial release" 11 | } 12 | 13 | "Files" 14 | { 15 | "Plugin" "Path_SM/plugins/botmanager-randomdifficulty.smx" 16 | "Source" "Path_SM/scripting/botmanager-randomdifficulty.sp" 17 | } 18 | } -------------------------------------------------------------------------------- /botmanager.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.3.0" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Added support for TF2 Classic" 11 | } 12 | 13 | "Files" 14 | { 15 | "Plugin" "Path_SM/plugins/botmanager.smx" 16 | "Source" "Path_SM/scripting/botmanager.sp" 17 | "Source" "Path_SM/scripting/mckayupdater.sp" 18 | "Source" "Path_SM/scripting/include/botmanager.inc" 19 | } 20 | } -------------------------------------------------------------------------------- /chatcolors.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "3.1.0" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Added support for Steam3 IDs" 11 | } 12 | 13 | "Files" 14 | { 15 | "Plugin" "Path_SM/plugins/custom-chatcolors.smx" 16 | "Package" "Path_SM/configs/custom-chatcolors.cfg" 17 | "Source" "Path_SM/scripting/custom-chatcolors.sp" 18 | "Source" "Path_SM/scripting/mckayupdater.sp" 19 | "Source" "Path_SM/scripting/include/ccc.inc" 20 | } 21 | } -------------------------------------------------------------------------------- /chatcolorsclantagmodule.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.0.1" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Added space between tag and name" 11 | } 12 | 13 | "Files" 14 | { 15 | "Plugin" "Path_SM/plugins/custom-chatcolors-clantag.smx" 16 | "Source" "Path_SM/scripting/custom-chatcolors-clantag.sp" 17 | } 18 | } -------------------------------------------------------------------------------- /chatcolorsdistinguishmodule.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.0.0" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Initial release" 11 | } 12 | 13 | "Files" 14 | { 15 | "Plugin" "Path_SM/plugins/custom-chatcolors-distinguish.smx" 16 | "Source" "Path_SM/scripting/custom-chatcolors-distinguish.sp" 17 | } 18 | } -------------------------------------------------------------------------------- /chatcolorsmysqlmodule.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.1.3" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Enforce uniqueness for identity field" 11 | } 12 | 13 | "Files" 14 | { 15 | "Plugin" "Path_SM/plugins/custom-chatcolors-mysql.smx" 16 | "Source" "Path_SM/scripting/custom-chatcolors-mysql.sp" 17 | } 18 | } -------------------------------------------------------------------------------- /chatcolorstogglemodule.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "2.0.0" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Updater improvements" 11 | "Notes" " - No longer unnecessarily writes rows to the Clientprefs table for every unique player" 12 | "Notes" " - Switched from deprecated forwards to preferred one" 13 | } 14 | 15 | "Files" 16 | { 17 | "Plugin" "Path_SM/plugins/custom-chatcolors-toggle.smx" 18 | "Source" "Path_SM/scripting/custom-chatcolors-toggle.sp" 19 | } 20 | } -------------------------------------------------------------------------------- /citybans.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.1.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Fixed a couple of issues" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/citybans.smx" 17 | "Source" "Path_SM/scripting/citybans.sp" 18 | "Source" "Path_SM/scripting/mckayupdater.sp" 19 | } 20 | } -------------------------------------------------------------------------------- /configs/custom-chatcolors.cfg: -------------------------------------------------------------------------------- 1 | // Custom Chat Colors is written by Dr. McKay (http://www.doctormckay.com) 2 | // Simple Chat Colors (Redux) is written by Antithasys 3 | // The configuration is very similar, so I've stolen Redux's documentation :P 4 | // 5 | // How to edit this file: 6 | // "admin_colors" <-- Leave this alone 7 | // { <-- Add all groups/steamids after first bracket (Leave this alone) 8 | // 9 | // "STEAM_0:1:1234567" <-- Here is a steamid example with a tag (don't duplicate steamids) 10 | // { 11 | // "namecolor" "#RRGGBB" <-- This is the color for the name (#RRGGBB in hex notation or #RRGGBBAA with alpha) 12 | // "textcolor" "#RRGGBBAA" <-- This is the color of the text 13 | // } 14 | // 15 | // "groupname" <-- This can either be a steamid for a specific player, or a group name 16 | // { <-- Open the group 17 | // "flag" "z" <-- This is the flag(s) assoicated with the group. This field doesn't matter if the group name is a steamid 18 | // "tag" "[admin]" <-- This is the text for the tag 19 | // "tagcolor" "O" <-- This is the color for the tag 20 | // "namecolor" "G" <-- This is the color for the name 21 | // "textcolor" "T" <-- This is the color of the text 22 | // } <-- Close the group 23 | // } <-- Add all groups/steamids before last bracket (Leave this alone) 24 | // 25 | // NOTE: 26 | // If you don't enter a steamid then the group name does not matter, it's just for your reference. 27 | // 28 | // For colors, either a hex notation of a color (#RRGGBB or #RRGGBBAA) or one of the supported shortcuts (O - Olive, G - Green, T - Team) is required 29 | // 30 | // --------ORDER OF OPERATIONS-------- 31 | // 32 | // The order in which you place items in the config file matters. Here is what determins what color they get: 33 | // 1. SteamID 34 | // If there is a steamid present, it will always override everything. If you put a steamid in twice 35 | // then the first entry (top to bottom) will be used. (I think, just don't do it!) 36 | // 2. Groups 37 | // The plugin will search (top to bottom) for a postitive match for the flag string. The player' flags 38 | // will be compared with the group flag character (NOTE: only one flag per group! "a" is okay, "ab" is NOT), 39 | // and if the player has the flag, it will stop there. 40 | // For example. Admins with the "ad" flags and donators with the "a" flag. If you place the "a" flag group 41 | // above the "d" group then the admin will get the "a" colors. Order matters. 42 | // 43 | // ---------DO NOT EDIT ABOVE THIS LINE--------- 44 | "admin_colors" 45 | { 46 | "STEAM_0:1:16" 47 | { 48 | "tag" "[BAILOPAN] " 49 | "tagcolor" "O" 50 | } 51 | "VIP" 52 | { 53 | "flag" "a" 54 | "tag" "[VIP] " 55 | "tagcolor" "#9EC34FAA" 56 | "namecolor" "#00CCFF" 57 | "textcolor" "#000000AA" 58 | } 59 | } -------------------------------------------------------------------------------- /connect_method.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.2.0" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Fixed some potential problems with late-load handling" 11 | } 12 | 13 | "Files" 14 | { 15 | "Plugin" "Path_SM/plugins/connect_method.smx" 16 | "Source" "Path_SM/scripting/connect_method.sp" 17 | "Source" "Path_SM/scripting/mckayupdater.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /convarfaker.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.0.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Initial release" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/convarfaker.smx" 17 | "Source" "Path_SM/scripting/convarfaker.sp" 18 | "Source" "Path_SM/scripting/mckayupdater.sp" 19 | } 20 | } -------------------------------------------------------------------------------- /data/backpack_viewer.txt: -------------------------------------------------------------------------------- 1 | "Viewers" 2 | { 3 | "backpacktf" 4 | { 5 | "name" "Backpack.tf" 6 | "url" "http://backpack.tf/profiles/{ID}" 7 | "idtype" "3" 8 | } 9 | 10 | "bazaar" 11 | { 12 | "name" "Bazaar.tf" 13 | "url" "http://bazaar.tf/backpack/{ID}" 14 | "idtype" "3" 15 | } 16 | 17 | "steam" 18 | { 19 | "name" "Steam" 20 | "url" "https://steamcommunity.com/profiles/{ID}/inventory#440" 21 | "idtype" "3" 22 | } 23 | 24 | "tf2b" 25 | { 26 | "name" "TF2B" 27 | "url" "http://tf2b.com/tf2/{ID}" 28 | "idtype" "3" 29 | } 30 | 31 | "tf2items" 32 | { 33 | "name" "TF2Items" 34 | "url" "http://www.tf2items.com/profiles/{ID}" 35 | "idtype" "3" 36 | } 37 | } -------------------------------------------------------------------------------- /endless_ctf.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.2.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Added endless_ctf_reset_flags cvar which controls whether carried/dropped flags are reset when a round is won" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/endless_ctf.smx" 17 | 18 | "Source" "Path_SM/scripting/endless_ctf.sp" 19 | "Source" "Path_SM/scripting/mckayupdater.sp" 20 | } 21 | } -------------------------------------------------------------------------------- /enhanced_items.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.1.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Fixed unicode issues in names with special characters" 12 | "Notes" " - Painted weapons now print the default game messages" 13 | "Notes" " - Plugin now only intercepts and rewrites methods which can contain multiple items of the same type" 14 | } 15 | 16 | "Files" 17 | { 18 | "Plugin" "Path_SM/plugins/enhanced_items.smx" 19 | 20 | "Source" "Path_SM/scripting/enhanced_items.sp" 21 | "Source" "Path_SM/scripting/mckayupdater.sp" 22 | } 23 | } -------------------------------------------------------------------------------- /game_desc_override.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.1.3" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Updater improvements" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/st_gamedesc_override.smx" 17 | "Source" "Path_SM/scripting/st_gamedesc_override.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /gamedata/arena-reloaded.games.txt: -------------------------------------------------------------------------------- 1 | "Games" 2 | { 3 | 4 | "tf" 5 | { 6 | "Offsets" 7 | 8 | { 9 | "SetWinningTeam" 10 | { 11 | "windows" "156" 12 | "linux" "157" 13 | } 14 | 15 | "GoToIntermission" 16 | { 17 | "windows" "148" 18 | "linux" "149" 19 | } 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /gamedata/detect_os.games.txt: -------------------------------------------------------------------------------- 1 | "Games" 2 | { 3 | "#default" 4 | { 5 | "#supported" 6 | { 7 | "game" "cstrike" 8 | "game" "tf" 9 | "game" "dod" 10 | "game" "hl2mp" 11 | "engine" "sdk2013" 12 | } 13 | 14 | "Keys" 15 | { 16 | "Convar_Windows" "windows_speaker_config" 17 | "Convar_Linux" "sdl_double_click_size" 18 | "Convar_Mac" "gl_can_mix_shader_gammas" 19 | } 20 | } 21 | 22 | "csgo" 23 | { 24 | "Keys" 25 | { 26 | "Convar_Windows" "windows_speaker_config" 27 | "Convar_Linux" "joy_gamecontroller_config" 28 | "Convar_Mac" "mac_fsbackground" 29 | } 30 | } 31 | 32 | "left4dead2" 33 | { 34 | "Keys" 35 | { 36 | "Convar_Windows" "windows_speaker_config" 37 | "Convar_Linux" "joy_gamecontroller_config" 38 | "Convar_Mac" "cl_debugrumble" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /humiliationconditions.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.0.0" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Initial release" 11 | } 12 | 13 | "Files" 14 | { 15 | "Plugin" "Path_SM/plugins/humiliationconditions.smx" 16 | "Source" "Path_SM/scripting/humiliationconditions.sp" 17 | "Source" "Path_SM/scripting/mckayupdater.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /humiliationglow.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.1.2" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Updater improvements" 11 | } 12 | 13 | "Files" 14 | { 15 | "Plugin" "Path_SM/plugins/humiliationglow.smx" 16 | "Source" "Path_SM/scripting/humiliationglow.sp" 17 | } 18 | } -------------------------------------------------------------------------------- /itemserver.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.1.5" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Fixed an error that occurred if a client left before their data is retreived from the database" 11 | } 12 | 13 | "Files" 14 | { 15 | "Plugin" "Path_SM/plugins/itemserver.smx" 16 | "Source" "Path_SM/scripting/itemserver.sp" 17 | } 18 | } -------------------------------------------------------------------------------- /kartify.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.5.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Removed cvar kartify_boost_recharge_time (use tf_halloween_kart_boost_recharge instead)" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/kartify.smx" 17 | 18 | "Source" "Path_SM/scripting/kartify.sp" 19 | "Source" "Path_SM/scripting/mckayupdater.sp" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /motd_text_http.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.0.1" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Fixed a Handle leak" 11 | } 12 | 13 | "Files" 14 | { 15 | "Plugin" "Path_SM/plugins/motd_text_http.smx" 16 | "Source" "Path_SM/scripting/motd_text_http.sp" 17 | "Source" "Path_SM/scripting/mckayupdater.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /mutecheck.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.9.2" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Updater improvements" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/mutecheck.smx" 17 | "Source" "Path_SM/scripting/mutecheck.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /namechange_fix.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.1.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Issue fixed by Valve; plugin now removes self on load" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/namechange_fix.smx" 17 | 18 | "Source" "Path_SM/scripting/namechange_fix.sp" 19 | "Source" "Path_SM/scripting/mckayupdater.sp" 20 | } 21 | } -------------------------------------------------------------------------------- /namelock.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.0.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Initial release" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/namelock.smx" 17 | "Source" "Path_SM/scripting/namelock.sp" 18 | "Source" "Path_SM/scripting/mckayupdater.sp" 19 | } 20 | } -------------------------------------------------------------------------------- /no_enemy_in_spawn.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.2.1" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Fixed an issue that caused detection to fail" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/no_enemy_in_spawn.smx" 17 | "Source" "Path_SM/scripting/no_enemy_in_spawn.sp" 18 | "Source" "Path_SM/scripting/mckayupdater.sp" 19 | } 20 | } -------------------------------------------------------------------------------- /player_analytics.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.3.1" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Updated gamedata" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/player_analytics.smx" 17 | "Plugin" "Path_SM/gamedata/detect_os.games.txt" 18 | "Source" "Path_SM/scripting/player_analytics.sp" 19 | "Source" "Path_SM/scripting/mckayupdater.sp" 20 | "Source" "Path_SM/scripting/include/player_analytics.inc" 21 | } 22 | } -------------------------------------------------------------------------------- /plugins/anticapslock.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/anticapslock.smx -------------------------------------------------------------------------------- /plugins/anyteleporter.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/anyteleporter.smx -------------------------------------------------------------------------------- /plugins/arena_reloaded.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/arena_reloaded.smx -------------------------------------------------------------------------------- /plugins/auto_steam_update.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/auto_steam_update.smx -------------------------------------------------------------------------------- /plugins/backpack-tf.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/backpack-tf.smx -------------------------------------------------------------------------------- /plugins/backpack_viewer.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/backpack_viewer.smx -------------------------------------------------------------------------------- /plugins/botmanager-names.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/botmanager-names.smx -------------------------------------------------------------------------------- /plugins/botmanager-randomdifficulty.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/botmanager-randomdifficulty.smx -------------------------------------------------------------------------------- /plugins/botmanager.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/botmanager.smx -------------------------------------------------------------------------------- /plugins/citybans.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/citybans.smx -------------------------------------------------------------------------------- /plugins/connect_method.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/connect_method.smx -------------------------------------------------------------------------------- /plugins/convarfaker.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/convarfaker.smx -------------------------------------------------------------------------------- /plugins/custom-chatcolors-clantag.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/custom-chatcolors-clantag.smx -------------------------------------------------------------------------------- /plugins/custom-chatcolors-distinguish.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/custom-chatcolors-distinguish.smx -------------------------------------------------------------------------------- /plugins/custom-chatcolors-mysql.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/custom-chatcolors-mysql.smx -------------------------------------------------------------------------------- /plugins/custom-chatcolors-toggle.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/custom-chatcolors-toggle.smx -------------------------------------------------------------------------------- /plugins/custom-chatcolors.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/custom-chatcolors.smx -------------------------------------------------------------------------------- /plugins/endless_ctf.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/endless_ctf.smx -------------------------------------------------------------------------------- /plugins/enhanced_items.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/enhanced_items.smx -------------------------------------------------------------------------------- /plugins/humiliationconditions.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/humiliationconditions.smx -------------------------------------------------------------------------------- /plugins/humiliationglow.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/humiliationglow.smx -------------------------------------------------------------------------------- /plugins/itemserver.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/itemserver.smx -------------------------------------------------------------------------------- /plugins/kartify.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/kartify.smx -------------------------------------------------------------------------------- /plugins/motd_text_http.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/motd_text_http.smx -------------------------------------------------------------------------------- /plugins/mutecheck.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/mutecheck.smx -------------------------------------------------------------------------------- /plugins/namechange_fix.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/namechange_fix.smx -------------------------------------------------------------------------------- /plugins/namelock.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/namelock.smx -------------------------------------------------------------------------------- /plugins/no_enemy_in_spawn.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/no_enemy_in_spawn.smx -------------------------------------------------------------------------------- /plugins/player_analytics.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/player_analytics.smx -------------------------------------------------------------------------------- /plugins/rainbowize.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/rainbowize.smx -------------------------------------------------------------------------------- /plugins/really_no_weapons.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/really_no_weapons.smx -------------------------------------------------------------------------------- /plugins/short_circuit_nerf.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/short_circuit_nerf.smx -------------------------------------------------------------------------------- /plugins/shutdowncountdown.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/shutdowncountdown.smx -------------------------------------------------------------------------------- /plugins/smac_autodemo.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/smac_autodemo.smx -------------------------------------------------------------------------------- /plugins/smdj.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/smdj.smx -------------------------------------------------------------------------------- /plugins/st_gamedesc_override.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/st_gamedesc_override.smx -------------------------------------------------------------------------------- /plugins/steamrep_checker.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/steamrep_checker.smx -------------------------------------------------------------------------------- /plugins/sticky_jumper_bombz.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/sticky_jumper_bombz.smx -------------------------------------------------------------------------------- /plugins/teamscores.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/teamscores.smx -------------------------------------------------------------------------------- /plugins/tidykick.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/tidykick.smx -------------------------------------------------------------------------------- /plugins/unrestricted_fov.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/unrestricted_fov.smx -------------------------------------------------------------------------------- /plugins/votekick_switcher.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/votekick_switcher.smx -------------------------------------------------------------------------------- /plugins/votescramble.smx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoctorMcKay/sourcemod-plugins/6c7ffca2b580b3b313ee2027ac4dd12b7fad226a/plugins/votescramble.smx -------------------------------------------------------------------------------- /rainbowize.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.7.0" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Improved Updater integration and SCP detection" 11 | } 12 | 13 | "Files" 14 | { 15 | "Plugin" "Path_SM/plugins/rainbowize.smx" 16 | "Source" "Path_SM/scripting/rainbowize.sp" 17 | } 18 | } -------------------------------------------------------------------------------- /really_no_weapons.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.0.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Initial release" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/really_no_weapons.smx" 17 | 18 | "Source" "Path_SM/scripting/really_no_weapons.sp" 19 | "Source" "Path_SM/scripting/mckayupdater.sp" 20 | } 21 | } -------------------------------------------------------------------------------- /scripting/anticapslock.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #define PLUGIN_VERSION "1.1.0" 7 | 8 | public Plugin:myinfo = { 9 | name = "[ANY] Anti Caps Lock", 10 | author = "Dr. McKay", 11 | description = "Forces text to lowercase when too many caps are used", 12 | version = PLUGIN_VERSION, 13 | url = "http://www.doctormckay.com" 14 | }; 15 | 16 | new Handle:g_cvarPctRequired; 17 | new Handle:g_cvarMinLength; 18 | 19 | #define UPDATE_FILE "anticapslock.txt" 20 | #define CONVAR_PREFIX "anti_caps_lock" 21 | 22 | #include "mckayupdater.sp" 23 | 24 | public OnPluginStart() { 25 | g_cvarPctRequired = CreateConVar("anti_caps_lock_percent", "0.9", "Force all letters to lowercase when this percent of letters is uppercase (not counting symbols)", _, true, 0.0, true, 1.0); 26 | g_cvarMinLength = CreateConVar("anti_caps_lock_min_length", "5", "Only force letters to lowercase when a message has at least this many letters (not counting symbols)", _, true, 0.0); 27 | } 28 | 29 | public Action:OnChatMessage(&author, Handle:recipients, String:name[], String:message[]) { 30 | if(CheckCommandAccess(author, "anti_caps_lock_immunity", ADMFLAG_ROOT, true)) { 31 | return Plugin_Continue; 32 | } 33 | 34 | new letters, uppercase, length = strlen(message); 35 | for(new i = 0; i < length; i++) { 36 | if(message[i] >= 'A' && message[i] <= 'Z') { 37 | uppercase++; 38 | letters++; 39 | } else if(message[i] >= 'a' && message[i] <= 'z') { 40 | letters++; 41 | } 42 | } 43 | 44 | if(letters >= GetConVarInt(g_cvarMinLength) && float(uppercase) / float(letters) >= GetConVarFloat(g_cvarPctRequired)) { 45 | // Force to lowercase 46 | for(new i = 0; i < length; i++) { 47 | if(message[i] >= 'A' && message[i] <= 'Z') { 48 | message[i] = CharToLower(message[i]); 49 | } 50 | } 51 | 52 | return Plugin_Changed; 53 | } 54 | 55 | return Plugin_Continue; 56 | } -------------------------------------------------------------------------------- /scripting/anyteleporter.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #undef REQUIRE_PLUGIN 7 | #include 8 | 9 | #define UPDATE_URL "http://hg.doctormckay.com/public-plugins/raw/default/anyteleporter.txt" 10 | #define PLUGIN_VERSION "1.3.1" 11 | 12 | public Plugin:myinfo = 13 | { 14 | name = "[TF2] AnyTeleporter", 15 | author = "Dr. McKay", 16 | description = "Toggles whether anybody can use anybody's teleporter", 17 | version = PLUGIN_VERSION, 18 | url = "http://www.doctormckay.com" 19 | } 20 | 21 | new Handle:defaultStateCvar; 22 | new bool:currentState = true; 23 | 24 | public OnPluginStart() { 25 | defaultStateCvar = CreateConVar("anyteleporter_default", "1", "AnyTeleporter default state (0 = no team restrictions)"); 26 | RegAdminCmd("sm_anyteleporter", Command_AnyTeleporter, ADMFLAG_BAN, "Toggles the ability for teleporters to be used by everyone"); 27 | } 28 | 29 | public OnMapStart() { 30 | currentState = GetConVarBool(defaultStateCvar); 31 | } 32 | 33 | public Action:Command_AnyTeleporter(client, args) { 34 | if(currentState) { 35 | currentState = false; 36 | ShowActivity2(client, "[SM] ", "Disabled teleporter team-restrictions"); 37 | LogAction(client, -1, "%L disabled teleporter restrictions", client); 38 | } else { 39 | currentState = true; 40 | ShowActivity2(client, "[SM] ", "Enabled teleporter team-restrictions"); 41 | LogAction(client, -1, "%L enabled teleporter restrictions", client); 42 | } 43 | return Plugin_Handled; 44 | } 45 | 46 | public Action:TF2_OnPlayerTeleport(client, teleporter, &bool:result) { 47 | if(currentState) { 48 | return Plugin_Continue; 49 | } else { 50 | result = true; 51 | return Plugin_Changed; 52 | } 53 | } 54 | 55 | ///////////////////////////////// 56 | 57 | public OnAllPluginsLoaded() { 58 | new Handle:convar; 59 | if(LibraryExists("updater")) { 60 | Updater_AddPlugin(UPDATE_URL); 61 | new String:newVersion[10]; 62 | Format(newVersion, sizeof(newVersion), "%sA", PLUGIN_VERSION); 63 | convar = CreateConVar("anyteleporter_version", newVersion, "AnyTeleporter Version", FCVAR_DONTRECORD|FCVAR_NOTIFY|FCVAR_CHEAT); 64 | } else { 65 | convar = CreateConVar("anyteleporter_version", PLUGIN_VERSION, "AnyTeleporter Version", FCVAR_DONTRECORD|FCVAR_NOTIFY|FCVAR_CHEAT); 66 | } 67 | HookConVarChange(convar, Callback_VersionConVarChanged); 68 | } 69 | 70 | public Callback_VersionConVarChanged(Handle:convar, const String:oldValue[], const String:newValue[]) { 71 | ResetConVar(convar); 72 | } 73 | 74 | public OnLibraryAdded(const String:name[]) { 75 | if(StrEqual(name, "updater")) { 76 | Updater_AddPlugin(UPDATE_URL); 77 | } 78 | } 79 | 80 | public Updater_OnPluginUpdated() { 81 | ReloadPlugin(); 82 | } -------------------------------------------------------------------------------- /scripting/arena_reloaded.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define PLUGIN_VERSION "1.0.0" 9 | 10 | public Plugin:myinfo = { 11 | name = "[TF2] Arena: Reloaded", 12 | author = "Dr. McKay", 13 | description = "Capturing the point in arena maps respawns the entire capping team", 14 | version = PLUGIN_VERSION, 15 | url = "http://www.doctormckay.com" 16 | }; 17 | 18 | new Handle:g_SetWinningTeam; 19 | new Handle:g_ChangeLevel; 20 | 21 | new Handle:g_cvarMarkForDeathTimeout; 22 | 23 | new bool:g_BlockNextIntermission; 24 | 25 | new Handle:g_UnmarkForDeathTimer[MAXPLAYERS + 1]; 26 | 27 | #define UPDATE_FILE "arena_reloaded.txt" 28 | #define CONVAR_PREFIX "arena_reloaded" 29 | 30 | #include "mckayupdater.sp" 31 | 32 | public OnPluginStart() { 33 | g_cvarMarkForDeathTimeout = CreateConVar("arena_reloaded_mark_for_death_fade", "2.0", "Time, in seconds, it takes for the marked-for-death status to fade after stepping off the point. -1 to disable mark for death entirely.", FCVAR_NOTIFY, true, -1.0, true, 30.0); 34 | 35 | HookEvent("controlpoint_starttouch", Event_StartTouchCP); 36 | HookEvent("controlpoint_endtouch", Event_EndTouchCP); 37 | HookEvent("teamplay_point_captured", Event_PointCaptured); 38 | 39 | new Handle:conf = LoadGameConfigFile("arena-reloaded.games"); 40 | if(conf == INVALID_HANDLE) { 41 | SetFailState("Gamedata file is missing or corrupt"); 42 | } 43 | 44 | new offset = GameConfGetOffset(conf, "SetWinningTeam"); 45 | g_SetWinningTeam = DHookCreate(offset, HookType_GameRules, ReturnType_Void, ThisPointer_Ignore, OnSetWinningTeam); 46 | DHookAddParam(g_SetWinningTeam, HookParamType_Int); 47 | DHookAddParam(g_SetWinningTeam, HookParamType_Int); 48 | DHookAddParam(g_SetWinningTeam, HookParamType_Bool); 49 | DHookAddParam(g_SetWinningTeam, HookParamType_Bool); 50 | DHookAddParam(g_SetWinningTeam, HookParamType_Bool); 51 | 52 | // Blocking SetWinningTeam causes GoToIntermission to be called, ending the map. We need to block that too. 53 | offset = GameConfGetOffset(conf, "GoToIntermission"); 54 | g_ChangeLevel = DHookCreate(offset, HookType_GameRules, ReturnType_Void, ThisPointer_Ignore, OnGoToIntermission); 55 | CloseHandle(conf); 56 | 57 | // Blocking SetWinningTeam also causes a HUD message of " Wins the Game!", so let's block that as well. 58 | HookUserMessage(GetUserMessageId("HudMsg"), OnHudText, true); 59 | } 60 | 61 | public OnMapStart() { 62 | if(g_SetWinningTeam == INVALID_HANDLE) { 63 | SetFailState("Unable to hook SetWinningTeam"); 64 | } 65 | 66 | decl String:map[32]; 67 | GetCurrentMap(map, sizeof(map)); 68 | if(StrContains(map, "arena_") != 0) { 69 | SetFailState("Arena: Reloaded can only run on arena maps"); 70 | } 71 | 72 | DHookGamerules(g_SetWinningTeam, false); 73 | DHookGamerules(g_ChangeLevel, false); 74 | 75 | g_BlockNextIntermission = false; 76 | } 77 | 78 | public MRESReturn:OnSetWinningTeam(Handle:params) { 79 | if(DHookGetParam(params, 2) == 1) { 80 | return MRES_Supercede; // Win due to point capture 81 | } 82 | 83 | return MRES_Ignored; 84 | } 85 | 86 | public MRESReturn:OnGoToIntermission(Handle:params) { 87 | if(g_BlockNextIntermission) { 88 | return MRES_Supercede; 89 | } 90 | 91 | return MRES_Ignored; 92 | } 93 | 94 | public Event_StartTouchCP(Handle:event, const String:name[], bool:dontBroadcast) { 95 | if(GetConVarFloat(g_cvarMarkForDeathTimeout) >= 0.0) { 96 | new client = GetEventInt(event, "player"); 97 | ClearHandle(g_UnmarkForDeathTimer[client]); 98 | TF2_AddCondition(client, TFCond_MarkedForDeathSilent, 9999999.9); 99 | } 100 | } 101 | 102 | public Event_EndTouchCP(Handle:event, const String:name[], bool:dontBroadcast) { 103 | new client = GetEventInt(event, "player"); 104 | ClearHandle(g_UnmarkForDeathTimer[client]); 105 | if(IsClientInGame(client)) { 106 | g_UnmarkForDeathTimer[client] = CreateTimer(GetConVarFloat(g_cvarMarkForDeathTimeout), Timer_UnmarkForDeath, GetClientUserId(client)); 107 | } 108 | } 109 | 110 | public Action:Timer_UnmarkForDeath(Handle:timer, any:userid) { 111 | new client = GetClientOfUserId(userid); 112 | TF2_RemoveCondition(client, TFCond_MarkedForDeathSilent); 113 | g_UnmarkForDeathTimer[client] = INVALID_HANDLE; 114 | } 115 | 116 | public Event_PointCaptured(Handle:event, const String:name[], bool:dontBroadcast) { 117 | new team = GetEventInt(event, "team"); 118 | for(new i = 1; i <= MaxClients; i++) { 119 | if(IsClientInGame(i) && !IsPlayerAlive(i) && GetClientTeam(i) == team) { 120 | TF2_RespawnPlayer(i); 121 | } 122 | } 123 | 124 | PrintToChatAll("Team %s has been respawned.", (team == 2) ? "RED" : "BLU"); 125 | } 126 | 127 | public Action:OnHudText(UserMsg:msg_id, Handle:msg, const players[], playersNum, bool:reliable, bool:init) { 128 | BfReadByte(msg); 129 | BfReadFloat(msg); 130 | BfReadFloat(msg); 131 | BfReadByte(msg); 132 | BfReadByte(msg); 133 | BfReadByte(msg); 134 | BfReadByte(msg); 135 | BfReadByte(msg); 136 | BfReadByte(msg); 137 | BfReadByte(msg); 138 | BfReadByte(msg); 139 | BfReadByte(msg); 140 | BfReadFloat(msg); 141 | BfReadFloat(msg); 142 | BfReadFloat(msg); 143 | BfReadFloat(msg); 144 | // Holy crap this message has a lot of parameters 145 | 146 | decl String:message[64]; 147 | BfReadString(msg, message, sizeof(message)); 148 | if(StrEqual(message, "Red Wins the Game!") || StrEqual(message, "Blue Wins the Game!")) { 149 | g_BlockNextIntermission = true; 150 | return Plugin_Handled; 151 | } 152 | 153 | return Plugin_Continue; 154 | } 155 | 156 | ClearHandle(&Handle:handle) { 157 | if(handle == INVALID_HANDLE) { 158 | return; 159 | } 160 | 161 | CloseHandle(handle); 162 | handle = INVALID_HANDLE; 163 | } -------------------------------------------------------------------------------- /scripting/botmanager-names.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #define PLUGIN_VERSION "1.0.0" 7 | 8 | public Plugin:myinfo = { 9 | name = "[TF2] Bot Names", 10 | author = "Dr. McKay", 11 | description = "Randomly assigns a name from a predetermined list to joining bots", 12 | version = PLUGIN_VERSION, 13 | url = "http://www.doctormckay.com" 14 | }; 15 | 16 | #define UPDATE_FILE "botmanager-names.txt" 17 | #define CONVAR_PREFIX "bot_manager_names" 18 | 19 | #include "mckayupdater.sp" 20 | 21 | new Handle:names; 22 | 23 | public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) { 24 | decl String:path[PLATFORM_MAX_PATH]; 25 | BuildPath(Path_SM, path, sizeof(path), "configs/botnames.ini"); 26 | new Handle:file = OpenFile(path, "r"); 27 | if(file == INVALID_HANDLE) { 28 | strcopy(error, err_max, "Unable to open configs/botnames.ini"); 29 | return APLRes_Failure; 30 | } 31 | 32 | names = CreateArray(MAX_NAME_LENGTH); 33 | decl String:name[MAX_NAME_LENGTH]; 34 | while(ReadFileLine(file, name, sizeof(name))) { 35 | new pos = StrContains(name, ";"); 36 | if(pos != -1) { 37 | strcopy(name, pos + 1, name); 38 | } 39 | 40 | TrimString(name); 41 | if(strlen(name) == 0) { 42 | continue; 43 | } 44 | 45 | PushArrayString(names, name); 46 | } 47 | CloseHandle(file); 48 | 49 | if(GetArraySize(names) == 0) { 50 | strcopy(error, err_max, "No names were found in configs/botnames.ini"); 51 | return APLRes_Failure; 52 | } 53 | 54 | return APLRes_Success; 55 | } 56 | 57 | public Bot_OnBotAdd(&TFClassType:class, &TFTeam:team, &difficulty, String:name[MAX_NAME_LENGTH]) { 58 | new iterations = 0; 59 | do { 60 | GetArrayString(names, GetRandomInt(0, GetArraySize(names) - 1), name, sizeof(name)); 61 | iterations++; 62 | if(iterations >= MaxClients) { 63 | LogError("Unable to find a name that isn't already taken in the server. You might want to add more names to botnames.ini."); 64 | name[0] = '\0'; 65 | return; 66 | } 67 | } while(PlayerIsInGame(name)); 68 | } 69 | 70 | bool:PlayerIsInGame(const String:name[]) { 71 | decl String:buffer[MAX_NAME_LENGTH]; 72 | for(new i = 1; i <= MaxClients; i++) { 73 | if(!IsClientInGame(i)) { 74 | continue; 75 | } 76 | GetClientName(i, buffer, sizeof(buffer)); 77 | if(StrEqual(name, buffer)) { 78 | return true; 79 | } 80 | } 81 | return false; 82 | } -------------------------------------------------------------------------------- /scripting/botmanager-randomdifficulty.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #define PLUGIN_VERSION "1.0.0" 7 | 8 | public Plugin:myinfo = { 9 | name = "[TF2] Random Bot Difficulty", 10 | author = "Dr. McKay", 11 | description = "Randomizes the difficulty of joining bots", 12 | version = PLUGIN_VERSION, 13 | url = "http://www.doctormckay.com" 14 | }; 15 | 16 | #define UPDATE_FILE "botmanager-randomdifficulty.txt" 17 | #define CONVAR_PREFIX "bot_manager_random_difficulty" 18 | 19 | #include "mckayupdater.sp" 20 | 21 | public Bot_OnBotAdd(&TFClassType:class, &TFTeam:team, &difficulty, String:name[MAX_NAME_LENGTH]) { 22 | difficulty = GetRandomInt(0, 3); 23 | } -------------------------------------------------------------------------------- /scripting/connect_method.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | 5 | #define PLUGIN_VERSION "1.2.0" 6 | 7 | public Plugin:myinfo = { 8 | name = "[ANY] Connection Method Viewer", 9 | author = "Dr. McKay", 10 | description = "Shows you how in-game players connected to the server", 11 | version = PLUGIN_VERSION, 12 | url = "http://www.doctormckay.com" 13 | }; 14 | 15 | new String:g_ConnectMethod[MAXPLAYERS + 1][64]; 16 | 17 | #define UPDATE_FILE "connect_method.txt" 18 | #define CONVAR_PREFIX "connect_method" 19 | 20 | #include "mckayupdater.sp" 21 | 22 | public OnPluginStart() { 23 | for(new i = 1; i <= MaxClients; i++) { 24 | if(IsClientConnected(i)) { 25 | OnClientConnected(i); 26 | } 27 | } 28 | 29 | RegAdminCmd("sm_connectmethod", Command_ConnectMethod, ADMFLAG_GENERIC, "Displays how all in-game players connected"); 30 | } 31 | 32 | public OnClientConnected(client) { 33 | if(IsFakeClient(client)) { 34 | return; 35 | } 36 | 37 | if(!GetClientInfo(client, "cl_connectmethod", g_ConnectMethod[client], sizeof(g_ConnectMethod[]))) { 38 | strcopy(g_ConnectMethod[client], sizeof(g_ConnectMethod[]), "Unknown"); 39 | } 40 | } 41 | 42 | public Action:Command_ConnectMethod(client, args) { 43 | new ReplySource:source = GetCmdReplySource(); 44 | if(client != 0 && source == SM_REPLY_TO_CHAT) { 45 | PrintToChat(client, "\x04[SM] \x01See console for output."); 46 | SetCmdReplySource(SM_REPLY_TO_CONSOLE); 47 | } 48 | 49 | ReplyToCommand(client, "[SM] Displaying connection method for all players..."); 50 | for(new i = 1; i <= MaxClients; i++) { 51 | if(!IsClientInGame(i) || IsFakeClient(i)) { 52 | continue; 53 | } 54 | 55 | ReplyToCommand(client, " - %-32N %s", i, g_ConnectMethod[i]); 56 | } 57 | 58 | SetCmdReplySource(source); 59 | return Plugin_Handled; 60 | } -------------------------------------------------------------------------------- /scripting/convarfaker.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | 5 | #define PLUGIN_VERSION "1.0.0" 6 | 7 | public Plugin:myinfo = { 8 | name = "[ANY] ConVar Faker", 9 | author = "Dr. McKay", 10 | description = "Fakes the values of cvars to clients", 11 | version = PLUGIN_VERSION, 12 | url = "http://www.doctormckay.com" 13 | }; 14 | 15 | new Handle:kv; 16 | new Handle:cache; 17 | 18 | #define UPDATE_FILE "convarfaker.txt" 19 | #define CONVAR_PREFIX "cvar_faker" 20 | 21 | #include "mckayupdater.sp" 22 | 23 | public OnPluginStart() { 24 | cache = CreateTrie(); 25 | LoadConfig(); 26 | 27 | RegAdminCmd("sm_cvar_faker_reload", Command_ReloadConfig, ADMFLAG_ROOT, "Reloads ConVar Faker's configuration"); 28 | } 29 | 30 | public Action:Command_ReloadConfig(client, args) { 31 | LogAction(client, -1, "%L reloaded ConVar Faker's configuration", client); 32 | ReplyToCommand(client, "\x04[SM] \x01Reloaded configuration"); 33 | LoadConfig(); 34 | return Plugin_Handled; 35 | } 36 | 37 | LoadConfig() { 38 | if(kv != INVALID_HANDLE) { 39 | CloseHandle(kv); 40 | } 41 | 42 | kv = CreateKeyValues("ConVar_Faker"); 43 | decl String:path[PLATFORM_MAX_PATH]; 44 | BuildPath(Path_SM, path, sizeof(path), "configs/cvar_faker.cfg"); 45 | 46 | if(!FileToKeyValues(kv, path)) { 47 | SetFailState("Configuration file is missing or invalid"); 48 | } 49 | 50 | for(new i = 1; i <= MaxClients; i++) { 51 | if(IsClientInGame(i)) { 52 | OnClientPostAdminCheck(i); 53 | } 54 | } 55 | } 56 | 57 | public OnClientPostAdminCheck(client) { 58 | if(IsFakeClient(client)) { 59 | return; 60 | } 61 | 62 | KvRewind(kv); 63 | KvGotoFirstSubKey(kv); 64 | decl String:cvarName[64], String:flags[16], String:flagType[16], String:value[128]; 65 | new Handle:cvar, AdminId:admin, AdminFlag:flag, bool:access; 66 | do { 67 | KvGetSectionName(kv, cvarName, sizeof(cvarName)); 68 | if(!GetTrieValue(cache, cvarName, cvar)) { 69 | cvar = FindConVar(cvarName); 70 | SetTrieValue(cache, cvarName, cvar); 71 | 72 | if(cvar == INVALID_HANDLE) { 73 | LogError("ConVar '%s' is invalid", cvarName); 74 | continue; 75 | } else if(!(GetConVarFlags(cvar) & FCVAR_REPLICATED)) { 76 | LogError("ConVar '%s' is not replicated", cvarName); 77 | SetTrieValue(cache, cvarName, INVALID_HANDLE); 78 | continue; 79 | } 80 | } 81 | 82 | if(cvar == INVALID_HANDLE) { 83 | continue; 84 | } 85 | 86 | KvGetString(kv, "flags", flags, sizeof(flags)); 87 | if(strlen(flags) > 0) { 88 | KvGetString(kv, "flagtype", flagType, sizeof(flagType)); 89 | admin = GetUserAdmin(client); 90 | 91 | if(StrEqual(flagType, "all", false)) { 92 | access = true; 93 | for(new i = 0; i < strlen(flags); i++) { 94 | FindFlagByChar(flags[i], flag); 95 | if(!GetAdminFlag(admin, flag)) { 96 | access = false; 97 | break; // Breaks out of flag loop 98 | } 99 | } 100 | } else if(StrEqual(flagType, "not", false)) { 101 | access = true; 102 | for(new i = 0; i < strlen(flags); i++) { 103 | FindFlagByChar(flags[i], flag); 104 | if(GetAdminFlag(admin, flag)) { 105 | access = false; 106 | break; 107 | } 108 | } 109 | } else { 110 | // any 111 | access = false; 112 | for(new i = 0; i < strlen(flags); i++) { 113 | FindFlagByChar(flags[i], flag); 114 | if(GetAdminFlag(admin, flag)) { 115 | access = true; 116 | break; // Breaks out of flag loop 117 | } 118 | } 119 | } 120 | 121 | if(!access) { 122 | continue; 123 | } 124 | } 125 | 126 | KvGetString(kv, "value", value, sizeof(value)); 127 | SendConVarValue(client, cvar, value); 128 | } while(KvGotoNextKey(kv)); 129 | } -------------------------------------------------------------------------------- /scripting/custom-chatcolors-clantag.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #undef REQUIRE_PLUGIN 8 | #include 9 | 10 | #define UPDATE_URL "http://hg.doctormckay.com/public-plugins/raw/default/chatcolorsclantagmodule.txt" 11 | #define PLUGIN_VERSION "1.0.1" 12 | 13 | public Plugin:myinfo = { 14 | name = "[CS] Custom Chat Colors Clan Tag Module", 15 | author = "Dr. McKay", 16 | description = "Automatically gives players a chat tag based on their current clan tag", 17 | version = PLUGIN_VERSION, 18 | url = "http://www.doctormckay.com" 19 | }; 20 | 21 | new Handle:cvarUsersOnly; 22 | new Handle:cvarColor; 23 | new Handle:cvarUpdater; 24 | 25 | public OnPluginStart() { 26 | cvarUsersOnly = CreateConVar("ccc_clantag_users_only", "1", "If 1, then only clients who aren't assigned a tag by custom-chatcolors.cfg (or the MySQL module) are given a clan tag"); 27 | cvarColor = CreateConVar("ccc_clantag_color", "G", "The color to give clan tags, in hexadecimal form (RRGGBB or RRGGBBAA). Special colors can be used: G for green, T for team color, O for olive, and blank for default"); 28 | cvarUpdater = CreateConVar("ccc_clantag_auto_update", "1", "Enables automatic updating (has no effect if Updater is not installed)"); 29 | } 30 | 31 | public CCC_OnUserConfigLoaded(client) { 32 | CreateTimer(5.0, Timer_SetClanTag, GetClientUserId(client)); // Delay so that the MySQL module can do its thing 33 | } 34 | 35 | public Action:Timer_SetClanTag(Handle:timer, any:userid) { 36 | new client = GetClientOfUserId(userid); 37 | if(client == 0) { 38 | return; 39 | } 40 | decl String:tag[64]; 41 | if(GetConVarBool(cvarUsersOnly)) { 42 | CCC_GetTag(client, tag, sizeof(tag)); 43 | if(strlen(tag) > 0) { 44 | return; // client already has a tag 45 | } 46 | } 47 | CS_GetClientClanTag(client, tag, sizeof(tag)); 48 | if(strlen(tag) == 0) { 49 | return; // Doesn't have a tag 50 | } 51 | decl String:color[16]; 52 | GetConVarString(cvarColor, color, sizeof(color)); 53 | if(StrEqual(color, "G", false)) { 54 | CCC_SetColor(client, CCC_TagColor, COLOR_GREEN, false); 55 | } else if(StrEqual(color, "O", false)) { 56 | CCC_SetColor(client, CCC_TagColor, COLOR_OLIVE, false); 57 | } else if(StrEqual(color, "T", false)) { 58 | CCC_SetColor(client, CCC_TagColor, COLOR_TEAM, false); 59 | } else if(strlen(color) == 6 || strlen(color) == 8) { 60 | CCC_SetColor(client, CCC_TagColor, StringToInt(color, 16), strlen(color) == 8); 61 | } else { 62 | CCC_SetColor(client, CCC_TagColor, COLOR_NONE, false); 63 | } 64 | 65 | StrCat(tag, sizeof(tag), " "); 66 | CCC_SetTag(client, tag); 67 | } 68 | 69 | ///////////////////////////////// 70 | 71 | public OnAllPluginsLoaded() { 72 | new Handle:convar; 73 | if(LibraryExists("updater")) { 74 | Updater_AddPlugin(UPDATE_URL); 75 | decl String:version[12]; 76 | Format(version, sizeof(version), "%sA", PLUGIN_VERSION); 77 | convar = CreateConVar("custom_chat_colors_clantag_version", version, "Custom Chat Colors Clan Tag Module Version", FCVAR_DONTRECORD|FCVAR_NOTIFY|FCVAR_CHEAT); 78 | } else { 79 | convar = CreateConVar("custom_chat_colors_clantag_version", PLUGIN_VERSION, "Custom Chat Colors Clan Tag Module Version", FCVAR_DONTRECORD|FCVAR_NOTIFY|FCVAR_CHEAT); 80 | } 81 | HookConVarChange(convar, Callback_VersionConVarChanged); 82 | Callback_VersionConVarChanged(convar, "", ""); // Check the cvar value 83 | } 84 | 85 | public OnLibraryAdded(const String:name[]) { 86 | if(StrEqual(name, "updater")) { 87 | Updater_AddPlugin(UPDATE_URL); 88 | } 89 | } 90 | 91 | public Callback_VersionConVarChanged(Handle:convar, const String:oldValue[], const String:newValue[]) { 92 | if(LibraryExists("updater")) { 93 | decl String:version[12]; 94 | Format(version, sizeof(version), "%sA", PLUGIN_VERSION); 95 | SetConVarString(convar, version); 96 | } else { 97 | SetConVarString(convar, PLUGIN_VERSION); 98 | } 99 | } 100 | 101 | public Action:Updater_OnPluginDownloading() { 102 | if(!GetConVarBool(cvarUpdater)) { 103 | return Plugin_Handled; 104 | } 105 | return Plugin_Continue; 106 | } 107 | 108 | public Updater_OnPluginUpdated() { 109 | ReloadPlugin(); 110 | } -------------------------------------------------------------------------------- /scripting/custom-chatcolors-distinguish.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #define PLUGIN_VERSION "1.0.0" 7 | 8 | public Plugin:myinfo = { 9 | name = "[Source 2009] Custom Chat Colors Distinguish Module", 10 | author = "Dr. McKay", 11 | description = "Controls what CCC aspects are visible based on a chat prefix", 12 | version = PLUGIN_VERSION, 13 | url = "http://www.doctormckay.com" 14 | }; 15 | 16 | #define UPDATE_FILE "chatcolorsdistinguishmodule.txt" 17 | #define CONVAR_PREFIX "custom_chat_colors_distinguish" 18 | 19 | #include "mckayupdater.sp" 20 | 21 | new Handle:cvarPrefix; 22 | new Handle:cvarTag; 23 | new Handle:cvarNameColor; 24 | new Handle:cvarChatColor; 25 | 26 | public OnPluginStart() { 27 | cvarPrefix = CreateConVar("sm_ccc_distinguish_prefix", "#", "Character or string that must be prefixed to a chat message to make it distinguished (case-sensitive)"); 28 | cvarTag = CreateConVar("sm_ccc_distinguish_tag", "-1", "-1 = display tag always, 0 = only display tag when not distinguished, 1 = only display tag when distinguished", _, true, -1.0, true, 1.0); 29 | cvarNameColor = CreateConVar("sm_ccc_distinguish_name", "-1", "-1 = color name always, 0 = only color name when not distinguished, 1 = only color name when distinguished", _, true, -1.0, true, 1.0); 30 | cvarChatColor = CreateConVar("sm_ccc_distinguish_chat", "-1", "-1 = color chat always, 0 = only color chat when not distinguished, 1 = only color chat when distinguished", _, true, -1.0, true, 1.0); 31 | } 32 | 33 | public Action:CCC_OnColor(client, const String:message[], CCC_ColorType:type) { 34 | new value = -1; 35 | 36 | switch(type) { 37 | case CCC_TagColor: value = GetConVarInt(cvarTag); 38 | case CCC_NameColor: value = GetConVarInt(cvarNameColor); 39 | case CCC_ChatColor: value = GetConVarInt(cvarChatColor); 40 | } 41 | 42 | if(value == -1) { 43 | return Plugin_Continue; 44 | } 45 | 46 | if(!IsMessageDistinguished(client, message)) { 47 | // Message is not distinguished 48 | if(value == 0) { 49 | return Plugin_Continue; 50 | } else { 51 | return Plugin_Handled; 52 | } 53 | } else { 54 | // Message is distinguished 55 | if(value == 0) { 56 | return Plugin_Handled; 57 | } else { 58 | return Plugin_Continue; 59 | } 60 | } 61 | } 62 | 63 | public CCC_OnChatMessage(client, String:message[], maxlen) { 64 | if(!IsMessageDistinguished(client, message)) { 65 | return; 66 | } 67 | 68 | new firstChar = FindFirstCharacter(message); 69 | decl String:prefix[64]; 70 | GetConVarString(cvarPrefix, prefix, sizeof(prefix)); 71 | for(new i = 0; i < strlen(prefix); i++) { 72 | RemoveChar(message, firstChar); 73 | } 74 | } 75 | 76 | bool:IsMessageDistinguished(client, const String:message[]) { 77 | if(!CheckCommandAccess(client, "sm_ccc_distinguish", 0, true)) { 78 | return false; 79 | } 80 | 81 | new firstChar = FindFirstCharacter(message); 82 | decl String:prefix[64]; 83 | GetConVarString(cvarPrefix, prefix, sizeof(prefix)); 84 | return (StrContains(message[firstChar], prefix) == 0); 85 | } 86 | 87 | FindFirstCharacter(const String:message[]) { 88 | new pos = 0; 89 | while(!IsValidCharacter(message[pos])) { 90 | if(message[pos] == '\x07') { 91 | pos += 7; 92 | } else if(message[pos] == '\x08') { 93 | pos += 9; 94 | } else { 95 | pos++; 96 | } 97 | } 98 | 99 | return pos; 100 | } 101 | 102 | bool:IsValidCharacter(char) { 103 | return !(char == '"' || char == ' ' || char == '\x01' || char == '\x02' || char == '\x03' || char == '\x04' || char == '\x05' || char == '\x06' || char == '\x07' || char == '\x08' || char == '\x09' || char == '\x10'); 104 | } 105 | 106 | RemoveChar(String:message[], index) { 107 | new len = strlen(message); 108 | for(new i = index; i < len; i++) { 109 | message[i] = message[i + 1]; 110 | } 111 | message[len - 1] = '\0'; 112 | } -------------------------------------------------------------------------------- /scripting/custom-chatcolors-toggle.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define PLUGIN_VERSION "2.0.0" 8 | 9 | public Plugin:myinfo = { 10 | name = "[Source 2013] Custom Chat Colors Toggle Module", 11 | author = "Dr. McKay, Mini", 12 | description = "Allows admins to toggle their chat colors", 13 | version = PLUGIN_VERSION, 14 | url = "http://www.doctormckay.com" 15 | }; 16 | 17 | new Handle:cookieTag; 18 | new Handle:cookieName; 19 | new Handle:cookieChat; 20 | new Handle:cvarDefaultTag; 21 | new Handle:cvarDefaultName; 22 | new Handle:cvarDefaultChat; 23 | 24 | #define UPDATE_FILE "chatcolorstogglemodule.txt" 25 | #define CONVAR_PREFIX "custom_chat_colors_toggle" 26 | 27 | #include "mckayupdater.sp" 28 | 29 | public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) { 30 | MarkNativeAsOptional("Updater_AddPlugin"); 31 | return APLRes_Success; 32 | } 33 | 34 | public OnPluginStart() { 35 | RegConsoleCmd("sm_togglecolors", Command_ToggleColors, "Toggles your chat colors"); 36 | RegConsoleCmd("sm_tc", Command_ToggleColors, "Toggles your chat colors"); 37 | cvarDefaultTag = CreateConVar("ccc_default_tag", "0", "When a user joins for the first time, should tags be disabled?"); 38 | cvarDefaultName = CreateConVar("ccc_default_name", "0", "When a user joins for the first time, should name colors be disabled?"); 39 | cvarDefaultChat = CreateConVar("ccc_default_chat", "0", "When a user joins for the first time, should chat colors be disabled?"); 40 | 41 | cookieTag = RegClientCookie("ccc_toggle_tag", "Custom Chat Colors Toggle - Tag", CookieAccess_Private); 42 | cookieName = RegClientCookie("ccc_toggle_name_color", "Custom Chat Colors Toggle - Name Color", CookieAccess_Private); 43 | cookieChat = RegClientCookie("ccc_toggle_chat_color", "Custom Chat Colors Toggle - Chat Color", CookieAccess_Private); 44 | SetCookieMenuItem(CustomChatColorMenu, 0, "Custom Chat Color Settings"); 45 | } 46 | 47 | public CustomChatColorMenu(client, CookieMenuAction:action, any:info, String:buffer[], maxlen) { 48 | if (action == CookieMenuAction_SelectOption) { 49 | ShowMenu(client); 50 | } 51 | } 52 | 53 | bool:GetCookieValue(client, Handle:cookie, Handle:defaultCvar) { 54 | decl String:value[8]; 55 | GetClientCookie(client, cookie, value, sizeof(value)); 56 | 57 | if(strlen(value) == 0) { 58 | return GetConVarBool(defaultCvar); 59 | } else { 60 | return bool:StringToInt(value); 61 | } 62 | } 63 | 64 | public MenuHandler_CPrefs(Handle:menu, MenuAction:action, client, param2) { 65 | if(action == MenuAction_End) { 66 | CloseHandle(menu); 67 | } 68 | 69 | else if(action == MenuAction_Select) { 70 | switch(param2) { 71 | case 0: { 72 | // tag 73 | new bool:value = GetCookieValue(client, cookieTag, cvarDefaultTag); 74 | SetClientCookie(client, cookieTag, value ? "0" : "1"); 75 | } 76 | case 1: { 77 | // name 78 | new bool:value = GetCookieValue(client, cookieName, cvarDefaultName); 79 | SetClientCookie(client, cookieName, value ? "0" : "1"); 80 | } 81 | case 2: { 82 | // chat 83 | new bool:value = GetCookieValue(client, cookieChat, cvarDefaultChat); 84 | SetClientCookie(client, cookieChat, value ? "0" : "1"); 85 | } 86 | case 3: { 87 | // allow all 88 | SetClientCookie(client, cookieTag, "0"); 89 | SetClientCookie(client, cookieName, "0"); 90 | SetClientCookie(client, cookieChat, "0"); 91 | } 92 | } 93 | 94 | ShowMenu(client); 95 | } 96 | } 97 | 98 | public Action:Command_ToggleColors(client, args) { 99 | if(client == 0) { 100 | ReplyToCommand(client, "[SM] This command can only be used in-game."); 101 | return Plugin_Handled; 102 | } 103 | 104 | ShowMenu(client); 105 | return Plugin_Handled; 106 | } 107 | 108 | ShowMenu(client) { 109 | new Handle:menu = CreateMenu(MenuHandler_CPrefs); 110 | SetMenuTitle(menu, "Choose Your Custom Chat Colors Settings"); 111 | decl String:buffer[64]; 112 | new bool:value, bool:allAllowed = true; 113 | 114 | value = GetCookieValue(client, cookieTag, cvarDefaultTag); 115 | if(value) allAllowed = false; 116 | Format(buffer, sizeof(buffer), value ? "Hide my Tag (Selected)" : "Hide my Tag"); 117 | AddMenuItem(menu, "tag", buffer); 118 | 119 | value = GetCookieValue(client, cookieName, cvarDefaultName); 120 | if(value) allAllowed = false; 121 | Format(buffer, sizeof(buffer), value ? "Hide my Name Color (Selected)" : "Hide my Name Color"); 122 | AddMenuItem(menu, "name", buffer); 123 | 124 | value = GetCookieValue(client, cookieChat, cvarDefaultChat); 125 | if(value) allAllowed = false; 126 | Format(buffer, sizeof(buffer), value ? "Hide my Chat Color (Selected)" : "Hide my Chat Color"); 127 | AddMenuItem(menu, "chat", buffer); 128 | 129 | Format(buffer, sizeof(buffer), allAllowed ? "Allow All (Selected)" : "Allow All"); 130 | AddMenuItem(menu, "allowall", buffer, allAllowed ? ITEMDRAW_DISABLED : ITEMDRAW_DEFAULT); 131 | 132 | SetMenuExitButton(menu, true); 133 | DisplayMenu(menu, client, MENU_TIME_FOREVER); 134 | } 135 | 136 | public Action:CCC_OnColor(client, const String:message[], CCC_ColorType:type) { 137 | new Handle:cookie, Handle:cvar; 138 | 139 | switch(type) { 140 | case CCC_TagColor: { 141 | cookie = cookieTag; 142 | cvar = cvarDefaultTag; 143 | } 144 | case CCC_NameColor: { 145 | cookie = cookieName; 146 | cvar = cvarDefaultName; 147 | } 148 | case CCC_ChatColor: { 149 | cookie = cookieChat; 150 | cvar = cvarDefaultChat; 151 | } 152 | } 153 | 154 | return GetCookieValue(client, cookie, cvar) ? Plugin_Handled : Plugin_Continue; 155 | } -------------------------------------------------------------------------------- /scripting/humiliationconditions.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #define PLUGIN_VERSION "1.0.0" 7 | 8 | #define COND_UBERCHARGED 1 9 | #define COND_UBERFADING 2 // Requires both TFCond_Ubercharged + TFCond_UberchargeFading 10 | #define COND_TELEGLOW 4 11 | #define COND_BUFFED 8 // Rings and glowing, Buff Banner effect 12 | #define COND_DEFBUFFED 16 // Rings and glowing, Battalion's Backup effect 13 | #define COND_CRITACOLA 32 // Mini-crits 14 | #define COND_JARATED 64 15 | #define COND_MILKED 128 16 | #define COND_MEGAHEAL 256 // Quick-fix effect, no healing 17 | #define COND_MARKFORDEATH 512 18 | #define COND_SPEEDBUFF 1024 // Effect of Disciplinary Action 19 | 20 | public Plugin:myinfo = { 21 | name = "[TF2] Humiliation Conditions", 22 | author = "Dr. McKay", 23 | description = "Applies conditions to players during humiliation round", 24 | version = PLUGIN_VERSION, 25 | url = "http://www.doctormckay.com" 26 | }; 27 | 28 | new Handle:cvarWinningTeam; 29 | new Handle:cvarLosingTeam; 30 | new Handle:cvarWinningTeamAdmin; 31 | new Handle:cvarLosingTeamAdmin; 32 | 33 | new Handle:mp_bonusroundtime; 34 | 35 | #define CONVAR_PREFIX "humiliation_conditions" 36 | #define UPDATE_FILE "humiliationconditions.txt" 37 | #include "mckayupdater.sp" 38 | 39 | public OnPluginStart() { 40 | cvarWinningTeam = CreateConVar("humiliation_conditions_winning_team", "0", "Sum of condition codes to be applied to winning team"); 41 | cvarLosingTeam = CreateConVar("humiliation_conditions_losing_team", "0", "Sum of condition codes to be applied to losing team"); 42 | cvarWinningTeamAdmin = CreateConVar("humiliation_conditions_winning_team_admin", "0", "Sum of condition codes to be applied to admins on winning team (controlled by humiliation_conditions_admin override"); 43 | cvarLosingTeamAdmin = CreateConVar("humiliation_conditions_losing_team_admin", "0", "Sum of condition codes to be applied to admins on losing team (controlled by humiliation_conditions_admin override"); 44 | AutoExecConfig(); 45 | 46 | mp_bonusroundtime = FindConVar("mp_bonusroundtime"); 47 | 48 | HookEvent("teamplay_round_win", Event_RoundEnd); 49 | } 50 | 51 | public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) { 52 | new winningTeam = GetEventInt(event, "team"); 53 | 54 | new team; 55 | for(new i = 1; i <= MaxClients; i++) { 56 | if(!IsClientInGame(i) || (team = GetClientTeam(i)) < 2) { 57 | continue; 58 | } 59 | if(team == winningTeam) { 60 | ApplyEffects(i, true, false); 61 | if(CheckCommandAccess(i, "humiliation_conditions_admin", ADMFLAG_RESERVATION, true)) { 62 | ApplyEffects(i, true, true); 63 | } 64 | } else { 65 | ApplyEffects(i, false, false); 66 | if(CheckCommandAccess(i, "humiliation_conditions_admin", ADMFLAG_RESERVATION, true)) { 67 | ApplyEffects(i, false, true); 68 | } 69 | } 70 | } 71 | } 72 | 73 | ApplyEffects(client, winner, admin) { 74 | new bits; 75 | if(winner) { 76 | bits = (!admin) ? GetConVarInt(cvarWinningTeam) : GetConVarInt(cvarWinningTeamAdmin); 77 | } else { 78 | bits = (!admin) ? GetConVarInt(cvarLosingTeam) : GetConVarInt(cvarLosingTeamAdmin); 79 | } 80 | new Float:time = GetConVarFloat(mp_bonusroundtime); 81 | if(bits & COND_UBERCHARGED) { 82 | TF2_AddCondition(client, TFCond_Ubercharged, time); 83 | } 84 | if(bits & COND_UBERFADING) { 85 | TF2_AddCondition(client, TFCond_UberchargeFading, time); 86 | } 87 | if(bits & COND_TELEGLOW) { 88 | TF2_AddCondition(client, TFCond_TeleportedGlow, time); 89 | } 90 | if(bits & COND_BUFFED) { 91 | TF2_AddCondition(client, TFCond_Buffed, time); 92 | } 93 | if(bits & COND_DEFBUFFED) { 94 | TF2_AddCondition(client, TFCond_DefenseBuffed, time); 95 | } 96 | if(bits & COND_CRITACOLA) { 97 | TF2_AddCondition(client, TFCond_CritCola, time); 98 | } 99 | if(bits & COND_JARATED) { 100 | TF2_AddCondition(client, TFCond_Jarated, time); 101 | } 102 | if(bits & COND_MILKED) { 103 | TF2_AddCondition(client, TFCond_Milked, time); 104 | } 105 | if(bits & COND_MEGAHEAL) { 106 | TF2_AddCondition(client, TFCond_MegaHeal, time); 107 | } 108 | if(bits & COND_MARKFORDEATH) { 109 | TF2_AddCondition(client, TFCond_MarkedForDeath, time); 110 | } 111 | if(bits & COND_SPEEDBUFF) { 112 | TF2_AddCondition(client, TFCond_SpeedBuffAlly, time); 113 | } 114 | } -------------------------------------------------------------------------------- /scripting/humiliationglow.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | 5 | #undef REQUIRE_PLUGIN 6 | #include 7 | 8 | #define UPDATE_URL "http://hg.doctormckay.com/public-plugins/raw/default/humiliationglow.txt" 9 | #define PLUGIN_VERSION "1.1.2" 10 | 11 | public Plugin:myinfo = { 12 | name = "[TF2] Humiliation Glow", 13 | author = "Dr. McKay", 14 | description = "Makes the losing team glow during humiliation", 15 | version = PLUGIN_VERSION, 16 | url = "http://www.doctormckay.com" 17 | } 18 | 19 | new Handle:updaterCvar; 20 | 21 | public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) { 22 | MarkNativeAsOptional("Updater_AddPlugin"); 23 | return APLRes_Success; 24 | } 25 | 26 | public OnPluginStart() { 27 | HookEvent("teamplay_round_start", Event_RoundStart); 28 | HookEvent("teamplay_round_win", Event_RoundWin); 29 | updaterCvar = CreateConVar("humiliation_glow_auto_update", "1", "Enables automatic updating (has no effect if Updater is not installed)"); 30 | } 31 | 32 | public Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast) { 33 | for(new i = 1; i <= MaxClients; i++) { 34 | if(IsClientInGame(i)) { 35 | SetEntProp(i, Prop_Send, "m_bGlowEnabled", 0, 1); 36 | } 37 | } 38 | } 39 | 40 | public Event_RoundWin(Handle:event, const String:name[], bool:dontBroadcast) { 41 | new winners = GetEventInt(event, "team"); 42 | new losers; 43 | if(winners == 2) { 44 | losers = 3; 45 | } else { 46 | losers = 2; 47 | } 48 | for(new i = 1; i <= MaxClients; i++) { 49 | if(IsClientInGame(i) && IsPlayerAlive(i) && GetClientTeam(i) == losers) { 50 | SetEntProp(i, Prop_Send, "m_bGlowEnabled", 1, 1); 51 | } 52 | } 53 | } 54 | 55 | ///////////////////////////////// 56 | 57 | public OnAllPluginsLoaded() { 58 | new Handle:convar; 59 | if(LibraryExists("updater")) { 60 | Updater_AddPlugin(UPDATE_URL); 61 | new String:newVersion[10]; 62 | Format(newVersion, sizeof(newVersion), "%sA", PLUGIN_VERSION); 63 | convar = CreateConVar("humiliation_glow_version", newVersion, "Humiliation Glow Version", FCVAR_DONTRECORD|FCVAR_NOTIFY|FCVAR_CHEAT); 64 | } else { 65 | convar = CreateConVar("humiliation_glow_version", PLUGIN_VERSION, "Humiliation Glow Version", FCVAR_DONTRECORD|FCVAR_NOTIFY|FCVAR_CHEAT); 66 | } 67 | HookConVarChange(convar, Callback_VersionConVarChanged); 68 | } 69 | 70 | public Callback_VersionConVarChanged(Handle:convar, const String:oldValue[], const String:newValue[]) { 71 | ResetConVar(convar); 72 | } 73 | 74 | public Action:Updater_OnPluginDownloading() { 75 | if(!GetConVarBool(updaterCvar)) { 76 | return Plugin_Handled; 77 | } 78 | return Plugin_Continue; 79 | } 80 | 81 | public OnLibraryAdded(const String:name[]) { 82 | if(StrEqual(name, "updater")) { 83 | Updater_AddPlugin(UPDATE_URL); 84 | } 85 | } 86 | 87 | public Updater_OnPluginUpdated() { 88 | ReloadPlugin(); 89 | } -------------------------------------------------------------------------------- /scripting/include/advanced_motd.inc: -------------------------------------------------------------------------------- 1 | #if defined _advmotd_enabled 2 | #endinput 3 | #endif 4 | #define _advmotd_enabled 5 | 6 | enum MOTDFailureReason { 7 | MOTDFailure_Unknown, // Failure reason unknown 8 | MOTDFailure_Disabled, // Client has explicitly disabled HTML MOTDs 9 | MOTDFailure_Matchmaking, // HTML MOTD is disabled by Quickplay/matchmaking (TF2 only) 10 | MOTDFailure_QueryFailed // cl_disablehtmlmotd convar query failed 11 | }; 12 | 13 | typedef MOTDFailure = function void (int client, MOTDFailureReason reason); 14 | 15 | /** 16 | * Displays an MOTD panel to a client with advanced options 17 | * 18 | * @param client Client index the panel should be shown to 19 | * @param title Title of the MOTD panel (not displayed on all games) 20 | * @param msg Content of the MOTD panel; could be a URL, plain text, or a stringtable index 21 | * @param type Type of MOTD this is, one of MOTDPANEL_TYPE_TEXT, MOTDPANEL_TYPE_INDEX, MOTDPANEL_TYPE_URL, MOTDPANEL_TYPE_FILE 22 | * @param visible Whether the panel should be shown to the client 23 | * @param big true if this should be a big MOTD panel (TF2 only) 24 | * @param verify true if we should check if the client can actually receive HTML MOTDs before sending it, false otherwise 25 | * @param callback A callback to be called if we determine that the client can't receive HTML MOTDs 26 | * @noreturn 27 | */ 28 | stock void AdvMOTD_ShowMOTDPanel(int client, const char[] title, const char[] msg, int type=MOTDPANEL_TYPE_INDEX, bool visible=true, bool big=false, bool verify=false, MOTDFailure callback=INVALID_FUNCTION) { 29 | char connectmethod[32]; 30 | if(verify && GetClientInfo(client, "cl_connectmethod", connectmethod, sizeof(connectmethod))) { 31 | if(StrContains(connectmethod, "quickplay", false) != -1 || StrContains(connectmethod, "matchmaking", false) != -1) { 32 | if(callback != INVALID_FUNCTION) { 33 | Call_StartFunction(null, callback); 34 | Call_PushCell(client); 35 | Call_PushCell(MOTDFailure_Matchmaking); 36 | Call_Finish(); 37 | } 38 | return; 39 | } 40 | } 41 | 42 | KeyValues kv = new KeyValues("data"); 43 | kv.SetString("title", title); 44 | kv.SetNum("type", type); 45 | kv.SetString("msg", msg); 46 | if(big) { 47 | kv.SetNum("customsvr", 1); 48 | } 49 | 50 | if(verify) { 51 | DataPack pack = new DataPack(); 52 | pack.WriteCell(kv); 53 | pack.WriteCell(visible); 54 | 55 | if(callback != INVALID_FUNCTION) { 56 | Handle fwd = CreateForward(ET_Ignore, Param_Cell, Param_Cell); 57 | AddToForward(fwd, null, callback); 58 | pack.WriteCell(fwd); 59 | } else { 60 | pack.WriteCell(0); 61 | } 62 | 63 | QueryClientConVar(client, "cl_disablehtmlmotd", AdvMOTD_OnQueryFinished, pack); 64 | } else { 65 | ShowVGUIPanel(client, "info", kv, visible); 66 | CloseHandle(kv); 67 | } 68 | } 69 | 70 | public void AdvMOTD_OnQueryFinished(QueryCookie cookie, int client, ConVarQueryResult result, const char[] cvarName, const char[] cvarValue, DataPack pack) { 71 | pack.Reset(); 72 | KeyValues kv = pack.ReadCell(); 73 | bool visible = pack.ReadCell(); 74 | Handle fwd = pack.ReadCell(); 75 | delete pack; 76 | 77 | if(result != ConVarQuery_Okay || StringToInt(cvarValue)) { 78 | delete kv; 79 | 80 | if(fwd) { 81 | Call_StartForward(fwd); 82 | Call_PushCell(client); 83 | Call_PushCell((result != ConVarQuery_Okay) ? MOTDFailure_QueryFailed : MOTDFailure_Disabled); 84 | delete fwd; 85 | } 86 | return; 87 | } 88 | 89 | ShowVGUIPanel(client, "info", kv, visible); 90 | delete kv; 91 | } 92 | -------------------------------------------------------------------------------- /scripting/include/botmanager.inc: -------------------------------------------------------------------------------- 1 | /** 2 | * Called when a bot is about to be added to the game 3 | * 4 | * @param class Class the bot will play as, by ref (this will change on death unless tf_bot_keep_class_after_death is set to 1), or TFClass_Unknown to allow the game to decide 5 | * @param team Team the bot will play on, by ref, or TFTeam_Unassigned to allow the game to decide 6 | * @param difficulty Difficulty the bot will play on, by ref, -1 = let game decide, 0 = easy, 1 = normal, 2 = hard, 3 = expert 7 | * @param name Name the bot will use, by ref, or empty to allow the game to decide 8 | * @noreturn 9 | */ 10 | forward Bot_OnBotAdd(&TFClassType:class, &TFTeam:team, &difficulty, String:name[MAX_NAME_LENGTH]); 11 | 12 | /** 13 | * Called when a bot is about to be removed from the game 14 | * 15 | * @param client Client index of the bot that will be dropped, by ref, override to choose a different bot 16 | * @noreturn 17 | */ 18 | forward Bot_OnBotKick(&client); 19 | 20 | public SharedPlugin:__pl_botmanager = { 21 | name = "botmanager", 22 | file = "botmanager.smx", 23 | #if defined REQUIRE_PLUGIN 24 | required = 1 25 | #else 26 | required = 0 27 | #endif 28 | }; -------------------------------------------------------------------------------- /scripting/include/bytebuffer.inc: -------------------------------------------------------------------------------- 1 | #if defined _bytebuffer_included 2 | #endinput 3 | #endif 4 | #define _bytebuffer_included 5 | 6 | #define BYTEBUFFER_VERSION 2 7 | 8 | #if !defined MAX_BUFFERS 9 | #define MAX_BUFFERS 32 10 | #endif 11 | 12 | #if !defined MAX_BUFFER_LENGTH 13 | #define MAX_BUFFER_LENGTH 1024 14 | #endif 15 | 16 | enum ByteBuffer { 17 | INVALID_BUFFER = -1 18 | }; 19 | 20 | static char g_Buffer[MAX_BUFFERS][MAX_BUFFER_LENGTH]; 21 | static bool g_InUse[MAX_BUFFERS]; 22 | static bool g_IsLE[MAX_BUFFERS]; 23 | static int g_Cursor[MAX_BUFFERS]; 24 | static int g_Length[MAX_BUFFERS]; 25 | 26 | methodmap ByteBuffer { 27 | property int Cursor { 28 | public get() { 29 | CheckBuffer(this); 30 | return g_Cursor[this]; 31 | } 32 | 33 | public set(int value) { 34 | CheckBuffer(this); 35 | g_Cursor[this] = value; 36 | } 37 | } 38 | 39 | property bool LittleEndian { 40 | public get() { 41 | CheckBuffer(this); 42 | return g_IsLE[this]; 43 | } 44 | 45 | public set(bool value) { 46 | CheckBuffer(this); 47 | g_IsLE[this] = value; 48 | } 49 | } 50 | 51 | property bool BigEndian { 52 | public get() { 53 | CheckBuffer(this); 54 | return !g_IsLE[this]; 55 | } 56 | 57 | public set(bool value) { 58 | CheckBuffer(this); 59 | g_IsLE[this] = !value; 60 | } 61 | } 62 | 63 | public void WriteByte(int data) { 64 | CheckBuffer(this); 65 | g_Buffer[this][this.Cursor] = data & 0x000000FF; 66 | this.Cursor++; 67 | } 68 | 69 | public void WriteShort(int data) { 70 | CheckBuffer(this); 71 | if(this.LittleEndian) { 72 | this.WriteByte(data & 0x000000FF); 73 | this.WriteByte((data & 0x0000FF00) >> 8); 74 | } else { 75 | this.WriteByte((data & 0x0000FF00) >> 8); 76 | this.WriteByte(data & 0x000000FF); 77 | } 78 | } 79 | 80 | public void WriteInt(int data) { 81 | CheckBuffer(this); 82 | if(this.LittleEndian) { 83 | this.WriteByte(data & 0x000000FF); 84 | this.WriteByte((data & 0x0000FF00) >> 8); 85 | this.WriteByte((data & 0x00FF0000) >> 16); 86 | this.WriteByte((data & 0xFF000000) >> 24); 87 | } else { 88 | this.WriteByte((data & 0xFF000000) >> 24); 89 | this.WriteByte((data & 0x00FF0000) >> 16); 90 | this.WriteByte((data & 0x0000FF00) >> 8); 91 | this.WriteByte(data & 0x000000FF); 92 | } 93 | } 94 | 95 | public void WriteString(const char[] input) { 96 | CheckBuffer(this); 97 | int length = strlen(input); 98 | for(int i = 0; i < length; i++) { 99 | this.WriteByte(view_as(input[i])); 100 | } 101 | 102 | this.WriteByte(0); 103 | } 104 | 105 | public int ReadByte() { 106 | CheckBuffer(this); 107 | int value = g_Buffer[this][this.Cursor] & 0xFF; 108 | this.Cursor++; 109 | return value; 110 | } 111 | 112 | public int ReadShort() { 113 | CheckBuffer(this); 114 | int a, b; 115 | 116 | if(this.LittleEndian) { 117 | a = this.ReadByte(); 118 | b = (this.ReadByte() << 8) & 0x0000FF00; 119 | } else { 120 | a = (this.ReadByte() << 8) & 0x0000FF00; 121 | b = this.ReadByte(); 122 | } 123 | 124 | return (a | b); 125 | } 126 | 127 | public int ReadInt() { 128 | CheckBuffer(this); 129 | int a, b, c, d; 130 | 131 | if(this.LittleEndian) { 132 | a = this.ReadByte(); 133 | b = (this.ReadByte() << 8) & 0x0000FF00; 134 | c = (this.ReadByte() << 16) & 0x00FF0000; 135 | d = (this.ReadByte() << 24) & 0xFF000000; 136 | } else { 137 | a = (this.ReadByte() << 24) & 0xFF000000; 138 | b = (this.ReadByte() << 16) & 0x00FF0000; 139 | c = (this.ReadByte() << 8) & 0x0000FF00; 140 | d = this.ReadByte(); 141 | } 142 | 143 | return (a | b | c | d); 144 | } 145 | 146 | public int ReadString(char[] output, int maxlen) { 147 | CheckBuffer(this); 148 | for(int i = 0; i < maxlen; i++) { 149 | output[i] = this.ReadByte(); 150 | 151 | if(output[i] == '\0') { 152 | return i + 1; 153 | } 154 | } 155 | 156 | return maxlen; 157 | } 158 | 159 | public int Dump(char[] output, int maxlen) { 160 | CheckBuffer(this); 161 | // Dump from start to cursor 162 | if(maxlen > this.Cursor) { 163 | maxlen = this.Cursor; 164 | } 165 | 166 | int i; 167 | for(i = 0; i < maxlen; i++) { 168 | output[i] = g_Buffer[this][i]; 169 | } 170 | 171 | return i; 172 | } 173 | 174 | public int Append(ByteBuffer buffer) { 175 | CheckBuffer(this); 176 | int length = buffer.Cursor; 177 | char[] dumped = new char[length]; 178 | buffer.Dump(dumped, length); 179 | 180 | for(int i = 0; i < length; i++) { 181 | this.WriteByte(dumped[i]); 182 | } 183 | 184 | return length; 185 | } 186 | 187 | public ByteBuffer Extract(int length) { 188 | CheckBuffer(this); 189 | ByteBuffer output = CreateByteBuffer(this.LittleEndian); 190 | 191 | for(int i = 0; i < length; i++) { 192 | output.WriteByte(this.ReadByte()); 193 | } 194 | 195 | output.Cursor = 0; 196 | return output; 197 | } 198 | 199 | public void Reset() { 200 | CheckBuffer(this); 201 | this.Cursor = 0; 202 | } 203 | 204 | public void Close() { 205 | CheckBuffer(this); 206 | g_InUse[this] = false; 207 | } 208 | } 209 | 210 | ByteBuffer CreateByteBuffer(bool littleEndian = true, const char data[] = "", int dataSize = 0) { 211 | int id = -1; 212 | for(int i = 0; i < MAX_BUFFERS; i++) { 213 | if(!g_InUse[i]) { 214 | id = i; 215 | break; 216 | } 217 | } 218 | 219 | if(id == -1) { 220 | ThrowError("Cannot allocate a new buffer: all %d buffers in use", MAX_BUFFERS); 221 | } 222 | 223 | g_InUse[id] = true; 224 | g_IsLE[id] = littleEndian; 225 | g_Cursor[id] = 0; 226 | g_Length[id] = 0; 227 | 228 | if(dataSize > 0) { 229 | // Write starting data 230 | if(dataSize >= MAX_BUFFER_LENGTH) { 231 | dataSize = MAX_BUFFER_LENGTH; 232 | } 233 | 234 | for(int i = 0; i < dataSize; i++) { 235 | g_Buffer[id][i] = data[i]; 236 | } 237 | } 238 | 239 | return view_as(id); 240 | } 241 | 242 | static void CheckBuffer(ByteBuffer index) { 243 | if(!g_InUse[index]) { 244 | ThrowError("Cannot read/write from closed buffer %d", index); 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /scripting/include/ccc.inc: -------------------------------------------------------------------------------- 1 | /** 2 | * This is the include file for Custom Chat Colors 3 | * https://forums.alliedmods.net/showthread.php?t=186695 4 | * To check that Custom Chat Colors is installed and running, verify that the "ccc" library exists 5 | */ 6 | 7 | #if defined _ccc_included 8 | #endinput 9 | #endif 10 | #define _ccc_included 11 | 12 | enum CCC_ColorType { 13 | CCC_TagColor, 14 | CCC_NameColor, 15 | CCC_ChatColor 16 | }; 17 | 18 | #define COLOR_NONE -1 19 | #define COLOR_GREEN -2 20 | #define COLOR_OLIVE -3 21 | #define COLOR_TEAM -4 22 | 23 | /** 24 | * Gets a client's color as a hexadecimal integer. 25 | * 26 | * @param client Client index 27 | * @param type Color type to retreive 28 | * @param alpha Pass a boolean variable by reference here and it will be true if the color has alpha specified or false if it doesn't (or is a stock color) 29 | * @return Color as a hexadecimal integer (use %X in formatting to get a hexadecimal string) 30 | * 31 | * On error/errors: Invalid client index or client is not in game 32 | */ 33 | native CCC_GetColor(client, CCC_ColorType:type, &bool:alpha = false); 34 | 35 | /** 36 | * Sets a client's color as a hexadecimal integer. 37 | * 38 | * @param client Client index 39 | * @param type Color type to set 40 | * @param color Integer representation of the color (use StringToInt(input, 16) to convert a hexadecimal string) or one of the color defines 41 | * @param alpha Are you specifying a color with alpha? 42 | * @return True if the color is updated successfully, false otherwise 43 | * 44 | * On error/errors: Invalid client index or client is not in game 45 | */ 46 | native bool:CCC_SetColor(client, CCC_ColorType:type, color, bool:alpha); 47 | 48 | /** 49 | * Gets a client's tag 50 | * 51 | * @param client Client index 52 | * @param buffer Buffer to store the tag in 53 | * @param maxlen Maximum buffer length 54 | * @noreturn 55 | * 56 | * On error/errors: Invalid client index or client is not in game 57 | */ 58 | native CCC_GetTag(client, String:buffer[], maxlen); 59 | 60 | /** 61 | * Sets a client's tag 62 | * 63 | * @param client Client index 64 | * @param tag String containing the new tag 65 | * @noreturn 66 | * 67 | * On error/errors: Invalid client index or client is not in game 68 | */ 69 | native CCC_SetTag(client, const String:tag[]); 70 | 71 | /** 72 | * Resets a client's color to the value in the config file. 73 | * 74 | * @param client Client index 75 | * @param type Color type to restore 76 | * @noreturn 77 | * 78 | * On error/errors: Invalid client index or client is not in game 79 | */ 80 | native CCC_ResetColor(client, CCC_ColorType:type); 81 | 82 | /** 83 | * Resets a client's tag to the value in the config file. 84 | * 85 | * @param client Client index 86 | * @noreturn 87 | * 88 | * On error/errors: Invalid client index or client is not in game 89 | */ 90 | native CCC_ResetTag(client); 91 | 92 | /** 93 | * Called when a cilent's name is about to be colored 94 | * DO NOT START A NEW USERMESSAGE (i.e. PrintToChat, PrintToChatAll) WITHIN THIS FORWARD 95 | * 96 | * @param client Client index 97 | * @return Plugin_Handled to prevent coloring, Plugin_Continue to allow coloring 98 | */ 99 | #pragma deprecated Use CCC_OnColor instead 100 | forward Action:CCC_OnNameColor(client); 101 | 102 | /** 103 | * Called when a client's chat is about to be colored 104 | * DO NOT START A NEW USERMESSAGE (i.e. PrintToChat, PrintToChatAll) WITHIN THIS FORWARD 105 | * 106 | * @param client Client index 107 | * @return Plugin_Handled to prevent coloring, Plugin_Continue to allow coloring 108 | */ 109 | #pragma deprecated Use CCC_OnColor instead 110 | forward Action:CCC_OnChatColor(client); 111 | 112 | /** 113 | * Called when a client's name is about to be tagged 114 | * DO NOT START A NEW USERMESSAGE (i.e. PrintToChat, PrintToChatAll) WITHIN THIS FORWARD 115 | * 116 | * @param client Client index 117 | * @return Plugin_Handled to prevent tagging, Plugin_Continue to allow tagging 118 | */ 119 | #pragma deprecated Use CCC_OnColor instead 120 | forward Action:CCC_OnTagApplied(client); 121 | 122 | /** 123 | * Called when a client's name is about to be tagged 124 | * DO NOT START A NEW USERMESSAGE (i.e. PrintToChat, PrintToChatAll) WITHIN THIS FORWARD 125 | * 126 | * @param client Client index 127 | * @param message Chat message that will be printed 128 | * @param type What type of color will be applied. If this is CCC_TagColor, it controls whether the tag will be applied at all, not whether the tag will be colored. 129 | * @return Plugin_Handled to prevent coloring, Plugin_Continue to allow coloring 130 | */ 131 | forward Action:CCC_OnColor(client, const String:message[], CCC_ColorType:type); 132 | 133 | /** 134 | * Called when a message has been fully colored and will be sent, unless further plugins modify it through Simple Chat Processor 135 | * 136 | * @param author Author client index 137 | * @param message Message 138 | * @param maxlen Maximum length of message buffer 139 | * @noreturn 140 | */ 141 | forward CCC_OnChatMessage(author, String:message[], maxlen); 142 | 143 | /** 144 | * Called when a client's colors and tag are about to be loaded from the config file 145 | * At this point, the client has NO COLORS 146 | * 147 | * @param client Client index 148 | * @return Plugin_Handled or Plugin_Stop to prevent loading, Plugin_Continue or Plugin_Changed to allow 149 | */ 150 | forward Action:CCC_OnUserConfigPreLoaded(client); 151 | 152 | /** 153 | * Called when a client's colors and tag have been loaded from the config file 154 | * 155 | * @param client Client index 156 | * @noreturn 157 | */ 158 | forward CCC_OnUserConfigLoaded(client); 159 | 160 | /** 161 | * Called when the configuration file is reloaded with the sm_reloadccc command 162 | * 163 | * @noreturn 164 | */ 165 | forward CCC_OnConfigReloaded(); 166 | 167 | public SharedPlugin:__pl_ccc = { 168 | name = "ccc", 169 | file = "custom-chatcolors.smx", 170 | #if defined REQUIRE_PLUGIN 171 | required = 1 172 | #else 173 | required = 0 174 | #endif 175 | }; 176 | 177 | #if !defined REQUIRE_PLUGIN 178 | public __pl_ccc_SetNTVOptional() { 179 | MarkNativeAsOptional("CCC_GetColor"); 180 | MarkNativeAsOptional("CCC_SetColor"); 181 | MarkNativeAsOptional("CCC_GetTag"); 182 | MarkNativeAsOptional("CCC_ResetTag"); 183 | MarkNativeAsOptional("CCC_ResetColor"); 184 | MarkNativeAsOptional("CCC_ResetTag"); 185 | } 186 | #endif -------------------------------------------------------------------------------- /scripting/include/player_analytics.inc: -------------------------------------------------------------------------------- 1 | #if defined _player_analytics_included 2 | #endinput 3 | #endif 4 | #define _player_analytics_included 5 | 6 | /** 7 | * Gets a client's connection ID in the database 8 | * 9 | * @param client Client index to get connection ID for 10 | * @return Client's connection ID or -1 if unavailable 11 | * @error If the client is not connected an error will be thrown. 12 | */ 13 | native int PA_GetConnectionID(int client); 14 | 15 | /** 16 | * Called when a client's connection has been logged to the database 17 | * 18 | * @param client Client index for whom the connection was logged 19 | * @param connID Connection ID for the client (same as ID returned by PA_GetConnectionID) 20 | * @noreturn 21 | */ 22 | forward void PA_OnConnectionLogged(int client, int connID); 23 | 24 | public SharedPlugin:__pl_player_analytics = { 25 | name = "player_analytics", 26 | file = "player_analyics.smx", 27 | #if defined REQUIRE_PLUGIN 28 | required = 1 29 | #else 30 | required = 0 31 | #endif 32 | }; 33 | 34 | #if !defined REQUIRE_PLUGIN 35 | public __pl_player_analytics_SetNTVOptional() { 36 | MarkNativeAsOptional("PA_GetConnectionID"); 37 | } 38 | #endif -------------------------------------------------------------------------------- /scripting/include/smdj.inc: -------------------------------------------------------------------------------- 1 | #if defined _smdj_included 2 | #endinput 3 | #endif 4 | #define _smdj_included 5 | 6 | /** 7 | * Called when a client starts to listen to a song. 8 | * 9 | * @param client Client index 10 | * @param title Song title 11 | * @noreturn 12 | */ 13 | forward SMDJ_OnStartListen(client, const String:title[]); 14 | 15 | 16 | public SharedPlugin:__pl_smdj = { 17 | name = "smdj", 18 | file = "smdj.smx", 19 | #if defined REQUIRE_PLUGIN 20 | required = 1 21 | #else 22 | required = 0 23 | #endif 24 | }; -------------------------------------------------------------------------------- /scripting/include/tidykick.inc: -------------------------------------------------------------------------------- 1 | #if defined _tidykick_included 2 | #endinput 3 | #endif 4 | #define _tidykick_included 5 | 6 | /** 7 | * Kicks a client without a "Disconnect: " prefix on the kick message 8 | * 9 | * @param client Client index to kick 10 | * @param reason Reason string (formatting rules) 11 | * @param ... Variable number of format parameters 12 | * @noreturn 13 | * @error If the client is not connected an error will be thrown. 14 | */ 15 | native TidyKickClient(client, const String:reason[], any:...); 16 | 17 | public SharedPlugin:__pl_tidykick = { 18 | name = "tidykick", 19 | file = "tidykick.smx", 20 | #if defined REQUIRE_PLUGIN 21 | required = 1 22 | #else 23 | required = 0 24 | #endif 25 | }; 26 | 27 | #if !defined REQUIRE_PLUGIN 28 | public __pl_tidykick_SetNTVOptional() { 29 | MarkNativeAsOptional("TidyKickClient"); 30 | } 31 | #endif -------------------------------------------------------------------------------- /scripting/kartify.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define PLUGIN_VERSION "1.5.0" 9 | 10 | public Plugin:myinfo = { 11 | name = "[TF2] Kartify", 12 | author = "Dr. McKay", 13 | description = "Put players into karts!", 14 | version = PLUGIN_VERSION, 15 | url = "http://www.doctormckay.com" 16 | }; 17 | 18 | new Handle:g_cvarSpawnKart; 19 | new Handle:g_cvarStartPercentage; 20 | new Handle:g_cvarForcedPercentage; 21 | new Handle:g_cvarAllowSuicide; 22 | 23 | new bool:g_KartSpawn[MAXPLAYERS + 1]; 24 | 25 | #define UPDATE_FILE "kartify.txt" 26 | #define CONVAR_PREFIX "kartify" 27 | 28 | #include "mckayupdater.sp" 29 | 30 | public OnPluginStart() { 31 | g_cvarSpawnKart = CreateConVar("kartify_spawn", "0", "0 = do nothing, 1 = put all players into karts when they spawn, 2 = put players into karts when they spawn only if sm_kartify was used on them", _, true, 0.0, true, 2.0); 32 | g_cvarStartPercentage = CreateConVar("kartify_start_percentage", "0", "Starting percentage, as an integer, of damage for kartified players", _, true, 0.0); 33 | g_cvarForcedPercentage = CreateConVar("kartify_forced_percentage", "-1", "If 0 or greater, karts will not take damage and will instead have this percent of damage all the time (as an integer)", _, true, -1.0); 34 | g_cvarAllowSuicide = CreateConVar("kartify_allow_suicide", "1", "Allow players to suicide while in a kart", _, true, 0.0, true, 1.0); 35 | 36 | RegAdminCmd("sm_kartify", Command_Kartify, ADMFLAG_SLAY, "Put players into karts!"); 37 | RegAdminCmd("sm_kart", Command_Kartify, ADMFLAG_SLAY, "Put players into karts!"); 38 | RegAdminCmd("sm_unkartify", Command_Unkartify, ADMFLAG_SLAY, "Remove players from karts"); 39 | RegAdminCmd("sm_unkart", Command_Unkartify, ADMFLAG_SLAY, "Remove players from karts"); 40 | RegAdminCmd("sm_kartifyme", Command_KartifyMe, ADMFLAG_SLAY, "Puts you into a kart!"); 41 | RegAdminCmd("sm_kartme", Command_KartifyMe, ADMFLAG_SLAY, "Puts you into a kart!"); 42 | RegAdminCmd("sm_unkartifyme", Command_UnkartifyMe, ADMFLAG_SLAY, "Removes you from a kart"); 43 | RegAdminCmd("sm_unkartme", Command_UnkartifyMe, ADMFLAG_SLAY, "Removes you from a kart"); 44 | 45 | LoadTranslations("common.phrases"); 46 | 47 | HookEvent("player_spawn", Event_PlayerSpawn); 48 | HookEvent("player_team", Event_PlayerTeam); 49 | 50 | AddCommandListener(Command_Kill, "kill"); 51 | AddCommandListener(Command_Kill, "explode"); 52 | } 53 | 54 | public Action:Command_Kill(client, const String:command[], argc) { 55 | if(GetConVarBool(g_cvarAllowSuicide)) { 56 | Unkartify(client); // Won't do anything if they're not in a kart 57 | } 58 | } 59 | 60 | public OnMapStart() { 61 | PrecacheModel("models/player/items/taunts/bumpercar/parts/bumpercar.mdl"); 62 | PrecacheModel("models/player/items/taunts/bumpercar/parts/bumpercar_nolights.mdl"); 63 | 64 | PrecacheSound(")weapons/bumper_car_accelerate.wav"); 65 | PrecacheSound(")weapons/bumper_car_decelerate.wav"); 66 | PrecacheSound(")weapons/bumper_car_decelerate_quick.wav"); 67 | PrecacheSound(")weapons/bumper_car_go_loop.wav"); 68 | PrecacheSound(")weapons/bumper_car_hit_ball.wav"); 69 | PrecacheSound(")weapons/bumper_car_hit_ghost.wav"); 70 | PrecacheSound(")weapons/bumper_car_hit_hard.wav"); 71 | PrecacheSound(")weapons/bumper_car_hit_into_air.wav"); 72 | PrecacheSound(")weapons/bumper_car_jump.wav"); 73 | PrecacheSound(")weapons/bumper_car_jump_land.wav"); 74 | PrecacheSound(")weapons/bumper_car_screech.wav"); 75 | PrecacheSound(")weapons/bumper_car_spawn.wav"); 76 | PrecacheSound(")weapons/bumper_car_spawn_from_lava.wav"); 77 | PrecacheSound(")weapons/bumper_car_speed_boost_start.wav"); 78 | PrecacheSound(")weapons/bumper_car_speed_boost_stop.wav"); 79 | 80 | decl String:name[64]; 81 | for(new i = 1; i <= 8; i++) { 82 | FormatEx(name, sizeof(name), "weapons/bumper_car_hit%d.wav", i); 83 | PrecacheSound(name); 84 | } 85 | } 86 | 87 | public OnClientConnected(client) { 88 | g_KartSpawn[client] = false; 89 | } 90 | 91 | public Action:Command_Kartify(client, args) { 92 | if(args == 0) { 93 | ReplyToCommand(client, "\x04[SM] \x01Usage: sm_kartify "); 94 | return Plugin_Handled; 95 | } 96 | 97 | decl String:argString[MAX_NAME_LENGTH]; 98 | GetCmdArgString(argString, sizeof(argString)); 99 | StripQuotes(argString); 100 | TrimString(argString); 101 | 102 | decl targets[MaxClients], String:target_name[MAX_NAME_LENGTH], bool:tn_is_ml; 103 | new result = ProcessTargetString(argString, client, targets, MaxClients, COMMAND_FILTER_ALIVE, target_name, sizeof(target_name), tn_is_ml); 104 | if(result <= 0) { 105 | ReplyToTargetError(client, result); 106 | return Plugin_Handled; 107 | } 108 | 109 | if(result == 1 && TF2_IsPlayerInCondition(targets[0], TFCond:82)) { 110 | // Only one player chosen and they're in a kart 111 | ShowActivity2(client, "\x04[SM] \x03", "\x01Unkartified \x03%s\x01!", target_name); 112 | LogAction(client, targets[0], "\"%L\" unkartified \"%L\"", client, targets[0]); 113 | g_KartSpawn[targets[0]] = false; 114 | Unkartify(targets[0]); 115 | return Plugin_Handled; 116 | } 117 | 118 | ShowActivity2(client, "\x04[SM] \x03", "\x01Kartified \x03%s\x01!", target_name); 119 | for(new i = 0; i < result; i++) { 120 | LogAction(client, targets[i], "\"%L\" kartified \"%L\"", client, targets[i]); 121 | g_KartSpawn[targets[i]] = true; 122 | Kartify(targets[i]); 123 | } 124 | 125 | return Plugin_Handled; 126 | } 127 | 128 | public Action:Command_Unkartify(client, args) { 129 | if(args == 0) { 130 | ReplyToCommand(client, "\x04[SM] \x01Usage: sm_unkartify "); 131 | return Plugin_Handled; 132 | } 133 | 134 | decl String:argString[MAX_NAME_LENGTH]; 135 | GetCmdArgString(argString, sizeof(argString)); 136 | StripQuotes(argString); 137 | TrimString(argString); 138 | 139 | decl targets[MaxClients], String:target_name[MAX_NAME_LENGTH], bool:tn_is_ml; 140 | new result = ProcessTargetString(argString, client, targets, MaxClients, COMMAND_FILTER_ALIVE, target_name, sizeof(target_name), tn_is_ml); 141 | if(result <= 0) { 142 | ReplyToTargetError(client, result); 143 | return Plugin_Handled; 144 | } 145 | 146 | ShowActivity2(client, "\x04[SM] \x03", "\x01Unkartified \x03%s\x01!", target_name); 147 | for(new i = 0; i < result; i++) { 148 | LogAction(client, targets[i], "\"%L\" unkartified \"%L\"", client, targets[i]); 149 | g_KartSpawn[targets[i]] = false; 150 | Unkartify(targets[i]); 151 | } 152 | 153 | return Plugin_Handled; 154 | } 155 | 156 | public Action:Command_KartifyMe(client, args) { 157 | if(TF2_IsPlayerInCondition(client, TFCond:82)) { 158 | Command_UnkartifyMe(client, 0); 159 | return Plugin_Handled; 160 | } 161 | 162 | ShowActivity2(client, "\x04[SM] \x03", "\x01Put self into a kart"); 163 | LogAction(client, client, "\"%L\" put themselves into a kart", client); 164 | g_KartSpawn[client] = true; 165 | Kartify(client); 166 | return Plugin_Handled; 167 | } 168 | 169 | public Action:Command_UnkartifyMe(client, args) { 170 | ShowActivity2(client, "\x04[SM] \x03", "\x01Removed self from a kart"); 171 | LogAction(client, client, "\"%L\" removed themselves from a kart", client); 172 | g_KartSpawn[client] = false; 173 | Unkartify(client); 174 | return Plugin_Handled; 175 | } 176 | 177 | public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) { 178 | new mode = GetConVarInt(g_cvarSpawnKart); 179 | if(mode == 0) { 180 | return; 181 | } 182 | 183 | new client = GetClientOfUserId(GetEventInt(event, "userid")); 184 | if(mode == 1 || (mode == 2 && g_KartSpawn[client])) { 185 | Kartify(client); 186 | } 187 | } 188 | 189 | public Event_PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) { 190 | new client = GetClientOfUserId(GetEventInt(event, "userid")); 191 | if(TF2_IsPlayerInCondition(client, TFCond:82)) { 192 | // Kill them otherwise they'll just spawn as the other team where they're standing 193 | Unkartify(client); 194 | ForcePlayerSuicide(client); 195 | } 196 | } 197 | 198 | Kartify(client) { 199 | TF2_AddCondition(client, TFCond:82, TFCondDuration_Infinite); 200 | SetEntProp(client, Prop_Send, "m_iKartHealth", GetConVarInt(g_cvarStartPercentage)); 201 | } 202 | 203 | Unkartify(client) { 204 | TF2_RemoveCondition(client, TFCond:82); 205 | } 206 | 207 | public OnGameFrame() { 208 | new forcedPct = GetConVarInt(g_cvarForcedPercentage); 209 | if(forcedPct >= 0) { 210 | for(new i = 1; i <= MaxClients; i++) { 211 | if(IsClientInGame(i)) { 212 | SetEntProp(i, Prop_Send, "m_iKartHealth", forcedPct); 213 | } 214 | } 215 | } 216 | } -------------------------------------------------------------------------------- /scripting/mckayupdater.sp: -------------------------------------------------------------------------------- 1 | /**************************************** 2 | * mckayupdater.sp 3 | * 4 | * This file is used in Dr. McKay's plugins for Updater integration 5 | * For more info on Dr. McKay's plugins, see http://www.doctormckay.com 6 | * For more info on Updater, see https://forums.alliedmods.net/showthread.php?t=169095 7 | * You may copy and use this file, but please be sure to change the URL to your own! 8 | * 9 | * This file does the following tasks: 10 | * - Adds the plugin to Updater's updating pool (using UPDATER_BASE_URL/UPDATE_FILE (UPDATE_FILE should be defined prior to including this file)) 11 | * - Creates a cvar CONVAR_PREFIX_auto_update to control whether Updater is enabled (CONVAR_PREFIX should be defined prior to including this file) 12 | * - Creates a version cvar CONVAR_PREFIX_version (CONVAR_PREFIX should be defined prior to including this file) 13 | * - Dynamically adds "A" to the version cvar based on whether Updater is installed and working 14 | * 15 | * If you need to put code into OnAllPluginsLoaded, define ALL_PLUGINS_LOADED_FUNC with a function (doesn't need to be public) to be called inside of OnAllPluginsLoaded 16 | * For example, #define ALL_PLUGINS_LOADED_FUNC AllPluginsLoaded 17 | * AllPluginsLoaded() { ... } 18 | * 19 | * If you need to put code into OnLibraryAdded, define LIBRARY_ADDED_FUNC with a function (doesn't need to be public) to be called inside of OnLibraryAdded 20 | * For example, #define LIBRARY_ADDED_FUNC LibraryAdded 21 | * LibraryAdded(const String:name[]) { ... } 22 | * 23 | * If you need to put code into OnLibraryRemoved, define LIBRARY_REMOVED_FUNC with a function (doesn't need to be public) to be called inside of OnLibraryRemoved 24 | * For example, #define LIBRARY_REMOVED_FUNC LibraryRemoved 25 | * LibraryRemoved(const String:name[]) { ... } 26 | * 27 | * Define RELOAD_ON_UPDATE and the plugin will reload itself upon being updated 28 | * 29 | */ 30 | 31 | #if defined _mckay_updater_included 32 | #endinput 33 | #endif 34 | #define _mckay_updater_included 35 | 36 | #if defined REQUIRE_PLUGIN 37 | #undef REQUIRE_PLUGIN 38 | #endif 39 | #include 40 | #define REQUIRE_PLUGIN 41 | 42 | #define UPDATER_BASE_URL "http://hg.doctormckay.com/public-plugins/raw/default" 43 | 44 | new Handle:cvarEnableUpdater; 45 | new Handle:cvarVersion; 46 | 47 | public OnAllPluginsLoaded() { 48 | decl String:cvarName[64]; 49 | Format(cvarName, sizeof(cvarName), "%s_auto_update", CONVAR_PREFIX); 50 | cvarEnableUpdater = CreateConVar(cvarName, "1", "Enables automatic updating (has no effect if Updater is not installed)"); 51 | 52 | Format(cvarName, sizeof(cvarName), "%s_version", CONVAR_PREFIX); 53 | cvarVersion = CreateConVar(cvarName, PLUGIN_VERSION, "Plugin Version", FCVAR_DONTRECORD|FCVAR_CHEAT|FCVAR_NOTIFY); 54 | 55 | HookConVarChange(cvarEnableUpdater, CheckUpdaterStatus); 56 | HookConVarChange(cvarVersion, CheckUpdaterStatus); 57 | CheckUpdaterStatus(INVALID_HANDLE, "", ""); 58 | 59 | #if defined ALL_PLUGINS_LOADED_FUNC 60 | ALL_PLUGINS_LOADED_FUNC(); 61 | #endif 62 | } 63 | 64 | public OnLibraryAdded(const String:name[]) { 65 | CheckUpdaterStatus(INVALID_HANDLE, "", ""); 66 | 67 | #if defined LIBRARY_ADDED_FUNC 68 | LIBRARY_ADDED_FUNC(name); 69 | #endif 70 | } 71 | 72 | public OnLibraryRemoved(const String:name[]) { 73 | CheckUpdaterStatus(INVALID_HANDLE, "", ""); 74 | 75 | #if defined LIBRARY_REMOVED_FUNC 76 | LIBRARY_REMOVED_FUNC(name); 77 | #endif 78 | } 79 | 80 | public CheckUpdaterStatus(Handle:convar, const String:name[], const String:value[]) { 81 | if(cvarVersion == INVALID_HANDLE) { 82 | return; // Version cvar not created yet 83 | } 84 | 85 | if(LibraryExists("updater") && GetConVarBool(cvarEnableUpdater)) { 86 | decl String:url[512], String:version[12]; 87 | Format(url, sizeof(url), "%s/%s", UPDATER_BASE_URL, UPDATE_FILE); 88 | Updater_AddPlugin(url); // Has no effect if we're already in Updater's pool 89 | 90 | Format(version, sizeof(version), "%sA", PLUGIN_VERSION); 91 | SetConVarString(cvarVersion, version); 92 | } else { 93 | SetConVarString(cvarVersion, PLUGIN_VERSION); 94 | } 95 | } 96 | 97 | public Action:Updater_OnPluginChecking() { 98 | if(!GetConVarBool(cvarEnableUpdater)) { 99 | return Plugin_Handled; 100 | } 101 | return Plugin_Continue; 102 | } 103 | 104 | #if defined RELOAD_ON_UPDATE 105 | public Updater_OnPluginUpdated() { 106 | ReloadPlugin(); 107 | } 108 | #endif -------------------------------------------------------------------------------- /scripting/motd_text_http.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define PLUGIN_VERSION "1.0.1" 8 | 9 | public Plugin:myinfo = { 10 | name = "[ANY] HTTP Text MOTD", 11 | author = "Dr. McKay", 12 | description = "Downloads a text file over HTTP and displays it as the text MOTD", 13 | version = PLUGIN_VERSION, 14 | url = "http://www.doctormckay.com" 15 | }; 16 | 17 | new Handle:g_cvarHost; 18 | new Handle:g_cvarPort; 19 | new Handle:g_cvarPath; 20 | new Handle:g_cvarWriteFile; 21 | new Handle:g_cvarMOTDFileText; 22 | new String:g_Buffer[4096]; 23 | 24 | #define UPDATE_FILE "motd_text_http.txt" 25 | #define CONVAR_PREFIX "motd_text" 26 | 27 | #include "mckayupdater.sp" 28 | 29 | public OnPluginStart() { 30 | g_cvarHost = CreateConVar("motd_text_host", "", "Host to download file from (domain or IP)\nExample: www.example.com"); 31 | g_cvarPort = CreateConVar("motd_text_port", "80", "Port your HTTP server is running on (usually 80)"); 32 | g_cvarPath = CreateConVar("motd_text_path", "/", "Path to request from your server\nExample: /motd_text.txt"); 33 | g_cvarWriteFile = CreateConVar("motd_text_write_file", "1", "If 1, writes the content of the downloaded file to the motd_text.txt file (or whatever file is specified by motdfile_text", _, true, 0.0, true, 1.0); 34 | AutoExecConfig(); 35 | g_cvarMOTDFileText = FindConVar("motdfile_text"); 36 | 37 | RegAdminCmd("sm_motd_text_redownload", Command_Redownload, ADMFLAG_ROOT, "Redownloads the motd_text.txt file"); 38 | } 39 | 40 | public Action:Command_Redownload(client, args) { 41 | DownloadFile(); 42 | ReplyToCommand(client, "\x04[SM] \x01File downloading..."); 43 | return Plugin_Handled; 44 | } 45 | 46 | public OnConfigsExecuted() { 47 | DownloadFile(); 48 | } 49 | 50 | DownloadFile() { 51 | g_Buffer[0] = '\0'; 52 | decl String:host[256]; 53 | GetConVarString(g_cvarHost, host, sizeof(host)); 54 | if(strlen(host) == 0) { 55 | LogMessage("Skipping file download, no host specified"); 56 | return; 57 | } 58 | new Handle:socket = SocketCreate(SOCKET_TCP, OnSocketError); 59 | SocketConnect(socket, OnSocketConnected, OnSocketReceive, OnSocketDisconnect, host, GetConVarInt(g_cvarPort)); 60 | SocketSetOption(socket, ConcatenateCallbacks, 12288); 61 | } 62 | 63 | public OnSocketConnected(Handle:socket, any:arg) { 64 | decl String:host[256], String:path[1024], String:request[2048]; 65 | GetConVarString(g_cvarHost, host, sizeof(host)); 66 | GetConVarString(g_cvarPath, path, sizeof(path)); 67 | Format(request, sizeof(request), "GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\nPragma: no-cache\r\nCache-Control: no-cache\r\n\r\n", path, host); 68 | SocketSend(socket, request); 69 | } 70 | 71 | public OnSocketReceive(Handle:socket, const String:receiveData[], const dataSize, any:arg) { 72 | StrCat(g_Buffer, sizeof(g_Buffer), receiveData); 73 | } 74 | 75 | public OnSocketDisconnect(Handle:socket, any:arg) { 76 | new pos = StrContains(g_Buffer, "\r\n\r\n"); 77 | new dataPos = pos + 4; 78 | 79 | decl String:headerstring[pos + 1]; 80 | strcopy(headerstring, pos + 1, g_Buffer); 81 | decl String:headers[64][128]; 82 | new total = ExplodeString(headerstring, "\r\n", headers, sizeof(headers), sizeof(headers[])); 83 | new statusCode = 0; 84 | for(new i = 0; i < total; i++) { 85 | if(StrContains(headers[i], "HTTP/") == 0) { 86 | pos = StrContains(headers[i], " ") + 1; 87 | new pos2 = pos + StrContains(headers[i][pos], " "); 88 | decl String:status[pos2 - pos + 1]; 89 | strcopy(status, pos2 - pos + 1, headers[i][pos]); 90 | statusCode = StringToInt(status); 91 | i = total; 92 | } 93 | } 94 | 95 | if(statusCode >= 300) { 96 | LogError("HTTP request failed. Status code: %d", statusCode); 97 | CloseHandle(socket); 98 | return; 99 | } 100 | 101 | decl String:data[4096]; 102 | strcopy(data, sizeof(data), g_Buffer[dataPos]); 103 | ReplaceString(data, sizeof(data), "\r", "\n"); 104 | 105 | if(g_cvarMOTDFileText != INVALID_HANDLE && GetConVarBool(g_cvarWriteFile)) { 106 | decl String:path[PLATFORM_MAX_PATH]; 107 | GetConVarString(g_cvarMOTDFileText, path, sizeof(path)); 108 | new Handle:file = OpenFile(path, "w"); 109 | WriteFileString(file, data, false); 110 | CloseHandle(file); 111 | } 112 | 113 | new bool:locked = LockStringTables(false); 114 | new table = FindStringTable("InfoPanel"); 115 | new index = FindStringIndex(table, "motd_text"); 116 | if(index < 0 || index > GetStringTableMaxStrings(table)) { 117 | AddToStringTable(table, "motd_text", data, sizeof(data)); 118 | } else { 119 | SetStringTableData(table, index, data, sizeof(data)); 120 | } 121 | LockStringTables(locked); 122 | 123 | CloseHandle(socket); 124 | } 125 | 126 | public OnSocketError(Handle:socket, const errorType, const errorNum, any:arg) { 127 | LogError("Socket error type %d, error num %d", errorType, errorNum); 128 | CloseHandle(socket); 129 | } -------------------------------------------------------------------------------- /scripting/mutecheck.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #undef REQUIRE_PLUGIN 7 | #include 8 | 9 | #define UPDATE_URL "http://hg.doctormckay.com/public-plugins/raw/default/mutecheck.txt" 10 | #define PLUGIN_VERSION "1.9.2" 11 | 12 | new String:tag[20]; 13 | new Handle:tagCvar = INVALID_HANDLE; 14 | new Handle:updaterCvar = INVALID_HANDLE; 15 | 16 | public Plugin:myinfo = { 17 | name = "[ANY] MuteCheck", 18 | author = "Dr. McKay", 19 | description = "Determine if anyone has muted a specific player and who", 20 | version = PLUGIN_VERSION, 21 | url = "http://www.doctormckay.com" 22 | }; 23 | 24 | public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) { 25 | MarkNativeAsOptional("Updater_AddPlugin"); 26 | return APLRes_Success; 27 | } 28 | 29 | public OnPluginStart() { 30 | tagCvar = CreateConVar("sm_mutecheck_tag", "[SM]", "Tag to be prepended to Mutecheck replies"); 31 | updaterCvar = CreateConVar("sm_mutecheck_auto_update", "1", "Enables automatic updating (has no effect if Updater is not installed)"); 32 | RegAdminCmd("sm_mutecheck", MuteCheck, 0, "Determine if anyone has muted a specific player and who"); 33 | LoadTranslations("common.phrases"); 34 | GetConVarString(tagCvar, tag, sizeof(tag)); 35 | HookConVarChange(tagCvar, TagChanged); 36 | } 37 | 38 | public TagChanged(Handle:cvar, const String:oldVal[], const String:newVal[]) { 39 | GetConVarString(tagCvar, tag, sizeof(tag)); 40 | } 41 | 42 | public OnAllPluginsLoaded() { 43 | if(LibraryExists("updater")) { 44 | Updater_AddPlugin(UPDATE_URL); 45 | new String:newVersion[10]; 46 | Format(newVersion, sizeof(newVersion), "%sA", PLUGIN_VERSION); 47 | CreateConVar("sm_mutecheck_version", newVersion, "MuteCheck Version", FCVAR_DONTRECORD|FCVAR_NOTIFY); 48 | } else { 49 | CreateConVar("sm_mutecheck_version", PLUGIN_VERSION, "MuteCheck Version", FCVAR_DONTRECORD|FCVAR_NOTIFY); 50 | } 51 | } 52 | 53 | public Action:MuteCheck(client, args) { 54 | if(args != 0 && args != 1) { 55 | ReplyToCommand(client, "%s Usage: sm_mutecheck to check yourself or sm_mutecheck [target] to check a target", tag); 56 | } 57 | if(args == 0) { 58 | if(client == 0) { 59 | ReplyToCommand(client, "%s Use sm_mutecheck [target] from the console.", tag); 60 | return Plugin_Handled; 61 | } 62 | new bool:mutes = false; 63 | decl String:muteMessage[512]; 64 | for(new i = 1; i <= MaxClients; i++) { 65 | if (!IsClientInGame(i) || IsFakeClient(i)) { 66 | continue; 67 | } 68 | if(IsClientMuted(i, client)) { 69 | if(!mutes) { 70 | mutes = true; 71 | GetClientName(i, muteMessage, sizeof(muteMessage)); 72 | } else { 73 | Format(muteMessage, sizeof(muteMessage), "%s, %N", muteMessage, i); 74 | } 75 | } 76 | } 77 | if(!mutes) { 78 | ReplyToCommand(client, "%s Muted by nobody.", tag); 79 | } else { 80 | ReplyToCommand(client, "%s Muted by %s.", tag, muteMessage); 81 | } 82 | } else if(args == 1) { 83 | if(!CheckCommandAccess(client, "sm_mutecheck_override", ADMFLAG_GENERIC)) { 84 | ReplyToCommand(client, "%s Usage: sm_mutecheck", tag); 85 | return Plugin_Handled; 86 | } 87 | decl String:arg1[MAX_NAME_LENGTH]; 88 | GetCmdArg(1, arg1, sizeof(arg1)); 89 | decl targets[MaxClients], String:target_name[MAX_NAME_LENGTH]; 90 | new bool:tn_is_ml; 91 | new total = ProcessTargetString(arg1, client, targets, MaxClients, COMMAND_FILTER_NO_IMMUNITY|COMMAND_FILTER_NO_BOTS, target_name, MAX_NAME_LENGTH, tn_is_ml); 92 | if(total < 1) { 93 | ReplyToTargetError(client, total); 94 | return Plugin_Handled; 95 | } 96 | decl String:muteMessage[512]; 97 | new bool:mutes; 98 | for(new i = 0; i < total; i++) { 99 | mutes = false; 100 | for(new j = 1; j <= MaxClients; j++) { 101 | if(!IsClientInGame(j) || IsFakeClient(j)) { 102 | continue; 103 | } 104 | if(IsClientMuted(j, targets[i])) { 105 | if(!mutes) { 106 | GetClientName(j, muteMessage, sizeof(muteMessage)); 107 | mutes = true; 108 | } else { 109 | Format(muteMessage, sizeof(muteMessage), "%s, %N", muteMessage, j); 110 | } 111 | } 112 | } 113 | if(!mutes) { 114 | ReplyToCommand(client, "%s %N is muted by nobody.", tag, targets[i]); 115 | } else { 116 | ReplyToCommand(client, "%s %N is muted by %s.", tag, targets[i], muteMessage); 117 | } 118 | } 119 | } 120 | return Plugin_Handled; 121 | } 122 | 123 | public Action:Updater_OnPluginDownloading() { 124 | if(!GetConVarBool(updaterCvar)) { 125 | return Plugin_Handled; 126 | } 127 | return Plugin_Continue; 128 | } 129 | 130 | public OnLibraryAdded(const String:name[]) { 131 | if(StrEqual(name, "updater")) { 132 | Updater_AddPlugin(UPDATE_URL); 133 | } 134 | } 135 | 136 | public Updater_OnPluginUpdated() { 137 | ReloadPlugin(); 138 | } -------------------------------------------------------------------------------- /scripting/namechange_fix.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #define PLUGIN_VERSION "1.1.0" 7 | 8 | public Plugin myinfo = { 9 | name = "[TF2] Name Change Oddities Fix", 10 | author = "Dr. McKay", 11 | description = "Deletes self", 12 | version = PLUGIN_VERSION, 13 | url = "http://www.doctormckay.com" 14 | }; 15 | 16 | #define UPDATE_FILE "namechange_fix.txt" 17 | #define CONVAR_PREFIX "namechange_fix" 18 | 19 | #include "mckayupdater.sp" 20 | 21 | #pragma newdecls required 22 | 23 | public void OnPluginStart() { 24 | char path[PLATFORM_MAX_PATH]; 25 | char filename[PLATFORM_MAX_PATH]; 26 | GetPluginFilename(null, filename, sizeof(filename)); 27 | BuildPath(Path_SM, path, sizeof(path), "plugins/%s", filename); 28 | 29 | DeleteFile(path); 30 | ServerCommand("sm plugins unload \"%s\"", filename); 31 | } -------------------------------------------------------------------------------- /scripting/namelock.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | 5 | #define PLUGIN_VERSION "1.0.0" 6 | 7 | public Plugin:myinfo = { 8 | name = "[TF2] Name Lock", 9 | author = "Dr. McKay", 10 | description = "Prevents name changes from certain players", 11 | version = PLUGIN_VERSION, 12 | url = "http://www.doctormckay.com" 13 | }; 14 | 15 | #define UPDATE_FILE "namelock.txt" 16 | #define CONVAR_PREFIX "name_lock" 17 | 18 | #include "mckayupdater.sp" 19 | 20 | public OnPluginStart() { 21 | RegAdminCmd("sm_namelock", Command_NameLock, ADMFLAG_BAN, "Prevents certain players from changing their name"); 22 | LoadTranslations("common.phrases"); 23 | } 24 | 25 | public Action:Command_NameLock(client, args) { 26 | if(args != 2) { 27 | ReplyToCommand(client, "\x04[SM] \x01Usage: sm_namelock <1|0>"); 28 | return Plugin_Handled; 29 | } 30 | 31 | decl String:arg1[MAX_NAME_LENGTH], String:arg2[2]; 32 | GetCmdArg(1, arg1, sizeof(arg1)); 33 | GetCmdArg(2, arg2, sizeof(arg2)); 34 | 35 | new bool:lock = bool:StringToInt(arg2); 36 | new targets[MaxClients], String:target_name[MAX_NAME_LENGTH], bool:tn_is_ml; 37 | new numTargets = ProcessTargetString(arg1, client, targets, MaxClients, COMMAND_FILTER_NO_BOTS, target_name, sizeof(target_name), tn_is_ml); 38 | if(numTargets <= 0) { 39 | ReplyToTargetError(client, numTargets); 40 | return Plugin_Handled; 41 | } 42 | 43 | for(new i = 0; i < numTargets; i++) { 44 | LogAction(client, targets[i], "\"%L\" %s name changes for \"%L\"", client, lock ? "locked" : "unlocked", targets[i]); 45 | DoNameLock(targets[i], lock); 46 | } 47 | 48 | ShowActivity2(client, "\x04[SM] \x03", "\x01%s name changes for \x03%s\x01.", lock ? "Locked" : "Unlocked", target_name); 49 | return Plugin_Handled; 50 | } 51 | 52 | DoNameLock(client, bool:lock) { 53 | ServerCommand("namelockid %d %d", GetClientUserId(client), lock ? 1 : 0); 54 | } -------------------------------------------------------------------------------- /scripting/no_enemy_in_spawn.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define PLUGIN_VERSION "1.2.1" 8 | 9 | public Plugin:myinfo = { 10 | name = "[TF2] No Enemies In Spawn", 11 | author = "Dr. McKay", 12 | description = "Slays anyone who manages to get into the enemy spawn", 13 | version = PLUGIN_VERSION, 14 | url = "http://www.doctormckay.com" 15 | }; 16 | 17 | new Handle:cvarMessage; 18 | 19 | new bool:roundRunning = true; 20 | 21 | #define UPDATE_FILE "no_enemy_in_spawn.txt" 22 | #define CONVAR_PREFIX "no_enemy_in_spawn" 23 | 24 | #include "mckayupdater.sp" 25 | 26 | public OnPluginStart() { 27 | cvarMessage = CreateConVar("no_enemy_in_spawn_message", "You may not enter the enemy team's spawn.", "Message to display when a player is slayed for entering the enemy spawn (blank for none)"); 28 | HookEvent("teamplay_round_start", Event_RoundStart); 29 | HookEvent("teamplay_round_win", Event_RoundEnd); 30 | HookEvent("teamplay_round_stalemate", Event_RoundEnd); 31 | } 32 | 33 | public Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast) { 34 | roundRunning = true; 35 | 36 | new i = -1; 37 | while((i = FindEntityByClassname(i, "func_respawnroom")) != -1) { 38 | SDKHook(i, SDKHook_TouchPost, OnTouchRespawnRoom); 39 | SDKHook(i, SDKHook_StartTouchPost, OnTouchRespawnRoom); 40 | } 41 | } 42 | 43 | public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) { 44 | roundRunning = false; 45 | } 46 | 47 | public OnTouchRespawnRoom(entity, other) { 48 | if(other < 1 || other > MaxClients || !IsPlayerAlive(other) || !roundRunning) { 49 | return; 50 | } 51 | if(GetEntProp(entity, Prop_Send, "m_iTeamNum") != GetClientTeam(other) && !CheckCommandAccess(other, "sm_admin", ADMFLAG_GENERIC)) { 52 | ForcePlayerSuicide(other); 53 | decl String:message[512]; 54 | GetConVarString(cvarMessage, message, sizeof(message)); 55 | if(!StrEqual(message, "")) { 56 | PrintCenterText(other, message); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /scripting/rainbowize.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #define PLUGIN_VERSION "1.7.0" 7 | 8 | public Plugin:myinfo = { 9 | name = "[TF2] Rainbowize", 10 | author = "Dr. McKay", 11 | description = "Rainbows!", 12 | version = PLUGIN_VERSION, 13 | url = "http://www.doctormckay.com" 14 | }; 15 | 16 | new bool:isRainbowized[MAXPLAYERS + 1] = {false, ...}; 17 | new Handle:colors; 18 | new Handle:randomCvar; 19 | new Handle:rainbowForward; 20 | 21 | #define UPDATE_FILE "rainbowize.txt" 22 | #define CONVAR_PREFIX "rainbowize" 23 | 24 | #include "mckayupdater.sp" 25 | 26 | public OnPluginStart() { 27 | RegAdminCmd("sm_rainbowize", Command_Rainbowize, ADMFLAG_CHAT, "Rainbowize!"); 28 | 29 | randomCvar = CreateConVar("sm_rainbowize_random", "0", "Should the order of the colors in the message be random?"); 30 | 31 | rainbowForward = CreateGlobalForward("OnRainbowizingChat", ET_Event, Param_Cell); 32 | LoadTranslations("common.phrases"); 33 | colors = CreateArray(12); 34 | decl String:path[PLATFORM_MAX_PATH]; 35 | BuildPath(Path_SM, path, sizeof(path), "configs/rainbowize_colors.ini"); 36 | if(!FileExists(path)) { 37 | PushArrayString(colors, "FF0000"); 38 | PushArrayString(colors, "FF7F00"); 39 | PushArrayString(colors, "FFD700"); 40 | PushArrayString(colors, "00AA00"); 41 | PushArrayString(colors, "0000FF"); 42 | PushArrayString(colors, "6600FF"); 43 | PushArrayString(colors, "8B00FF"); 44 | } else { 45 | new Handle:file = OpenFile(path, "r"); 46 | decl String:line[64]; 47 | while(ReadFileLine(file, line, sizeof(line))) { 48 | line[6] = '\0'; // effectively substring 0, 6 49 | StringToUpper(line); 50 | if(strlen(line) != 6 || !IsValidHexadecimal(line)) { 51 | LogError("Invalid color detected in rainbowize_colors.ini. Problem on line: %s", line); 52 | } else { 53 | PushArrayString(colors, line); 54 | } 55 | } 56 | if(GetArraySize(colors) == 0) { 57 | LogError("No colors found in rainbowize_colors.ini file. Reverting to default."); 58 | PushArrayString(colors, "FF0000"); 59 | PushArrayString(colors, "FF7F00"); 60 | PushArrayString(colors, "FFD700"); 61 | PushArrayString(colors, "00AA00"); 62 | PushArrayString(colors, "0000FF"); 63 | PushArrayString(colors, "6600FF"); 64 | PushArrayString(colors, "8B00FF"); 65 | } 66 | CloseHandle(file); 67 | } 68 | } 69 | 70 | bool:IsValidHexadecimal(const String:input[]) { 71 | for(new i = 0; ; i++) { 72 | if(input[i] == '\0') { 73 | break; // I'd rather return true here, but the compiler whines 74 | } 75 | if(!CharInString(input[i], "0123456789ABCDEF")) { 76 | return false; 77 | } 78 | } 79 | return true; 80 | } 81 | 82 | bool:CharInString(chr, const String:string[]) { 83 | for(new i = 0; ; i++) { 84 | if(string[i] == '\0') { 85 | break; // I'd rather return false here, but the compiler whines 86 | } 87 | if(string[i] == chr) { 88 | return true; 89 | } 90 | } 91 | return false; 92 | } 93 | 94 | StringToUpper(String:input[]) { 95 | for(new i = 0; ; i++) { 96 | if(input[i] == '\0') { 97 | return; 98 | } 99 | input[i] = CharToUpper(input[i]); 100 | } 101 | } 102 | 103 | public OnClientConnected(client) { 104 | isRainbowized[client] = false; 105 | } 106 | 107 | public Action:Command_Rainbowize(client, args) { 108 | if(args != 0 && args != 1 && args != 2) { 109 | ReplyToCommand(client, "[SM] Usage: sm_rainbowize [1/0]"); 110 | return Plugin_Handled; 111 | } 112 | if(args == 0) { 113 | if(isRainbowized[client]) { 114 | isRainbowized[client] = false; 115 | } else { 116 | isRainbowized[client] = true; 117 | } 118 | ShowActivity2(client, "[SM] ", "Toggled rainbow chat on self."); 119 | LogAction(client, client, "%L toggled rainbow chat on themself", client); 120 | return Plugin_Handled; 121 | } 122 | if(!CheckCommandAccess(client, "RainbowizeTargetOthers", ADMFLAG_CHAT)) { 123 | ReplyToCommand(client, "[SM] Usage: sm_rainbowize"); 124 | return Plugin_Handled; 125 | } 126 | if(args == 1) { 127 | decl String:target_name[MAX_NAME_LENGTH]; 128 | new target_list[MAXPLAYERS]; 129 | new target_count; 130 | new bool:tn_is_ml; 131 | decl String:arg1[MAX_NAME_LENGTH]; 132 | GetCmdArg(1, arg1, sizeof(arg1)); 133 | if((target_count = ProcessTargetString(arg1, client, target_list, MAXPLAYERS, COMMAND_FILTER_NO_BOTS, target_name, sizeof(target_name), tn_is_ml)) <= 0) { 134 | ReplyToTargetError(client, target_count); 135 | return Plugin_Handled; 136 | } 137 | for(new i = 0; i < target_count; i++) { 138 | if(isRainbowized[target_list[i]]) { 139 | isRainbowized[target_list[i]] = false; 140 | } else { 141 | isRainbowized[target_list[i]] = true; 142 | } 143 | LogAction(client, target_list[i], "%L toggled rainbow chat on %L", client, target_list[i]); 144 | } 145 | ShowActivity2(client, "[SM] ", "Toggled rainbow chat on %s.", target_name); 146 | return Plugin_Handled; 147 | } 148 | if(args == 2) { 149 | decl String:target_name[MAX_NAME_LENGTH]; 150 | new target_list[MAXPLAYERS]; 151 | new target_count; 152 | new bool:tn_is_ml; 153 | decl String:arg1[MAX_NAME_LENGTH], String:arg2[4]; 154 | GetCmdArg(1, arg1, sizeof(arg1)); 155 | GetCmdArg(2, arg2, sizeof(arg2)); 156 | new iState = StringToInt(arg2); 157 | if(iState != 0 && iState != 1) { 158 | ReplyToCommand(client, "[SM] Usage: sm_rainbowize [1/0]"); 159 | return Plugin_Handled; 160 | } 161 | new bool:bState = false; 162 | if(iState == 1) { 163 | bState = true; 164 | } 165 | decl String:sState[8]; 166 | if(bState) { 167 | strcopy(sState, sizeof(sState), "on"); 168 | } else { 169 | strcopy(sState, sizeof(sState), "off"); 170 | } 171 | if((target_count = ProcessTargetString(arg1, client, target_list, MAXPLAYERS, COMMAND_FILTER_NO_BOTS, target_name, sizeof(target_name), tn_is_ml)) <= 0) { 172 | ReplyToTargetError(client, target_count); 173 | return Plugin_Handled; 174 | } 175 | for(new i = 0; i < target_count; i++) { 176 | isRainbowized[target_list[i]] = bState; 177 | LogAction(client, target_list[i], "%L set rainbow chat on %L %s", client, target_list[i], sState); 178 | } 179 | ShowActivity2(client, "[SM] ", "Set rainbow chat on %s %s", target_name, sState); 180 | return Plugin_Handled; 181 | } 182 | ReplyToCommand(client, "[SM] An unknown error occurred."); 183 | return Plugin_Handled; 184 | } 185 | 186 | public Action:OnChatMessage(&author, Handle:recipients, String:name[], String:message[]) { 187 | if(!isRainbowized[author] || !RainbowForward(author)) { 188 | return Plugin_Continue; 189 | } 190 | TrimString(message); 191 | decl String:buffers[64][64]; 192 | new parts = ExplodeString(message, " ", buffers, sizeof(buffers), sizeof(buffers[])); 193 | new bool:first = true; 194 | new bool:random = GetConVarBool(randomCvar); 195 | new colorIndex = 0; 196 | decl String:color[12]; 197 | if(random) { 198 | colorIndex = GetRandomInt(0, GetArraySize(colors) - 1); 199 | } 200 | new String:final[256]; 201 | for(new i = 0; i < parts; i++) { 202 | if(first) { 203 | first = false; 204 | } else { 205 | StrCat(final, sizeof(final), " "); 206 | } 207 | GetArrayString(colors, colorIndex, color, sizeof(color)); 208 | Format(final, sizeof(final), "%s\x07%s%s", final, color, buffers[i]); 209 | if(random) { 210 | colorIndex = GetRandomInt(0, GetArraySize(colors) - 1); 211 | } else { 212 | colorIndex++; 213 | if(colorIndex >= GetArraySize(colors)) { 214 | colorIndex = 0; 215 | } 216 | } 217 | } 218 | StripQuotes(final); 219 | strcopy(message, MAXLENGTH_MESSAGE, final); 220 | return Plugin_Changed; 221 | } 222 | 223 | public Action:CCC_OnChatColor(client) { 224 | if(isRainbowized[client]) { 225 | return Plugin_Handled; 226 | } 227 | return Plugin_Continue; 228 | } 229 | 230 | bool:RainbowForward(author) { 231 | new Action:result = Plugin_Continue; 232 | Call_StartForward(rainbowForward); 233 | Call_PushCell(author); 234 | Call_Finish(result); 235 | if(result == Plugin_Handled || result == Plugin_Stop) { 236 | return false; 237 | } 238 | return true; 239 | } -------------------------------------------------------------------------------- /scripting/really_no_weapons.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define PLUGIN_VERSION "1.0.0" 8 | 9 | public Plugin:myinfo = { 10 | name = "[TF2] Really, no weapons", 11 | author = "Dr. McKay", 12 | description = "Disables sentries during Merasmus' no-weapons curse", 13 | version = PLUGIN_VERSION, 14 | url = "http://www.doctormckay.com" 15 | }; 16 | 17 | #define UPDATE_FILE "really_no_weapons.txt" 18 | #define CONVAR_PREFIX "really_no_weapons" 19 | 20 | #include "mckayupdater.sp" 21 | 22 | public TF2_OnConditionAdded(client, TFCond:condition) { 23 | if(condition == TFCond:85) { 24 | // See if everyone is melee-only 25 | for(new i = 1; i <= MaxClients; i++) { 26 | if(IsClientInGame(i) && IsPlayerAlive(i) && !TF2_IsPlayerInCondition(i, TFCond:85)) { 27 | return; 28 | } 29 | } 30 | 31 | // Everyone is melee-only, disable all sentries 32 | SetSentryDisabled(true); 33 | } 34 | } 35 | 36 | public TF2_OnConditionRemoved(client, TFCond:condition) { 37 | if(condition == TFCond:85) { 38 | SetSentryDisabled(false); 39 | } 40 | } 41 | 42 | SetSentryDisabled(bool:disabled) { 43 | new ent = -1; 44 | while((ent = FindEntityByClassname(ent, "obj_sentrygun")) != -1) { 45 | SetEntProp(ent, Prop_Send, "m_bDisabled", disabled); 46 | } 47 | } -------------------------------------------------------------------------------- /scripting/short_circuit_nerf.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define PLUGIN_VERSION "1.0.2" 8 | #define WEAPON_SHORT_CIRCUIT 528 9 | 10 | public Plugin:myinfo = { 11 | name = "[TF2] Nerf Short Circuit NAO", 12 | author = "Dr. McKay", 13 | description = "Nerfs the now hilariously-overpowered Short Circuit", 14 | version = PLUGIN_VERSION, 15 | url = "http://www.doctormckay.com" 16 | }; 17 | 18 | new Handle:g_cvarFiringDelay; 19 | new Handle:g_cvarMetalCost; 20 | 21 | new g_LastFire[MAXPLAYERS + 1]; 22 | 23 | #define UPDATE_FILE "short_circuit_nerf.txt" 24 | #define CONVAR_PREFIX "short_circuit_nerf" 25 | 26 | #include "mckayupdater.sp" 27 | 28 | public OnPluginStart() { 29 | g_cvarFiringDelay = CreateConVar("short_circuit_nerf_delay_seconds", "0.8", "Number of seconds to restrict Short Circuit firing after an attack", _, true, 0.1); 30 | g_cvarMetalCost = CreateConVar("short_circuit_nerf_metal_cost", "20", "Metal the Short Circuit should cost per fire", _, true, 5.0); 31 | 32 | AddNormalSoundHook(OnNormalSound); 33 | } 34 | 35 | public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon, &subtype, &cmdnum, &tickcount, &seed, mouse[2]) { 36 | if(!IsPlayerAlive(client)) { 37 | return Plugin_Continue; 38 | } 39 | 40 | new wep = GetEntPropEnt(client, Prop_Send, "m_hActiveWeapon"); 41 | if(wep == -1 || !IsValidEntity(wep)) { 42 | return Plugin_Continue; 43 | } 44 | 45 | if(GetEntProp(wep, Prop_Send, "m_iItemDefinitionIndex") != WEAPON_SHORT_CIRCUIT) { 46 | return Plugin_Continue; 47 | } 48 | 49 | if(GetEntPropFloat(wep, Prop_Send, "m_flNextPrimaryAttack") > GetGameTime()) { 50 | buttons &= ~IN_ATTACK; 51 | return Plugin_Changed; 52 | } 53 | 54 | return Plugin_Continue; 55 | } 56 | 57 | public Action:OnNormalSound(clients[64], &numClients, String:sample[PLATFORM_MAX_PATH], &entity, &channel, &Float:volume, &level, &pitch, &flags) { 58 | // This is the only way I could find to hook when the player fires the Short Circuit 59 | if(entity < 1 || entity > MaxClients || StrContains(sample, "barret_arm_shot.wav") == -1 || g_LastFire[entity] == GetGameTickCount()) { 60 | return; 61 | } 62 | 63 | g_LastFire[entity] = GetGameTickCount(); 64 | new difference = GetConVarInt(g_cvarMetalCost) - 5; 65 | new metal = GetEntProp(entity, Prop_Data, "m_iAmmo", 4, 3); 66 | metal -= difference; 67 | if(metal < 0) { 68 | metal = 0; 69 | } 70 | SetEntProp(entity, Prop_Data, "m_iAmmo", metal, 4, 3); 71 | 72 | if(metal > 0) { 73 | CreateTimer(0.0, Timer_UpdateAttackTime, GetClientUserId(entity)); 74 | } 75 | } 76 | 77 | public Action:Timer_UpdateAttackTime(Handle:timer, any:userid) { 78 | new client = GetClientOfUserId(userid); 79 | if(client != 0) { 80 | SetEntPropFloat(GetPlayerWeaponSlot(client, 1), Prop_Send, "m_flNextPrimaryAttack", GetGameTime() + GetConVarFloat(g_cvarFiringDelay)); 81 | } 82 | } -------------------------------------------------------------------------------- /scripting/shutdowncountdown.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #undef REQUIRE_PLUGIN 7 | #tryinclude 8 | 9 | #define UPDATE_URL "http://hg.doctormckay.com/public-plugins/raw/default/shutdowncountdown.txt" 10 | #define PLUGIN_VERSION "1.6.2" 11 | 12 | new shutdownTime; 13 | new String:tag[20]; 14 | new String:messageBeginning[100]; 15 | new String:messageEnd[100]; 16 | new Handle:shutdownTimer = INVALID_HANDLE; 17 | new Handle:notifyCvar = INVALID_HANDLE; 18 | new Handle:tagCvar = INVALID_HANDLE; 19 | new Handle:messageBeginningCvar = INVALID_HANDLE; 20 | new Handle:messageEndCvar = INVALID_HANDLE; 21 | new Handle:updaterCvar = INVALID_HANDLE; 22 | 23 | public Plugin:myinfo = { 24 | name = "[Any] Shutdown Countdown", 25 | author = "Dr. McKay", 26 | description = "Lets an admin start a countdown to a server shutdown", 27 | version = PLUGIN_VERSION, 28 | url = "http://www.doctormckay.com" 29 | }; 30 | 31 | public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) { 32 | MarkNativeAsOptional("Updater_AddPlugin"); 33 | return APLRes_Success; 34 | } 35 | 36 | public OnPluginStart() { 37 | notifyCvar = CreateConVar("sm_shutdown_countdown_notify", "30", "The countdown will also be displayed in the center of the screen when it is below this many seconds."); 38 | tagCvar = CreateConVar("sm_shutdown_countdown_tag", "[SM]", "The tag that will be prepended to command replies"); 39 | messageBeginningCvar = CreateConVar("sm_shutdown_countdown_beginning", "WARNING: The server will shut down in", "The beginning of the timer message"); 40 | messageEndCvar = CreateConVar("sm_shutdown_countdown_end", "seconds.", "The end of the timer message"); 41 | updaterCvar = CreateConVar("sm_shutdown_countdown_auto_update", "1", "Enables automatic updating (has no effect if Updater is not installed)"); 42 | RegAdminCmd("sm_shutdown", Command_ShutdownCountdown, ADMFLAG_RCON, "Start a server shutdown countdown"); 43 | RegAdminCmd("sm_shutdown_confirm", Command_ConfirmShutdown, ADMFLAG_RCON, "Confirms a pending server shutdown countdown"); 44 | RegAdminCmd("sm_shutdown_cancel", Command_CancelShutdown, ADMFLAG_RCON, "Cancels a pending server shutdown countdown"); 45 | shutdownTime = 0; 46 | GetConVarString(tagCvar, tag, sizeof(tag)); 47 | GetConVarString(messageBeginningCvar, messageBeginning, sizeof(messageBeginning)); 48 | GetConVarString(messageEndCvar, messageEnd, sizeof(messageEnd)); 49 | HookConVarChange(tagCvar, CvarChanged); 50 | HookConVarChange(messageBeginningCvar, CvarChanged); 51 | HookConVarChange(messageEndCvar, CvarChanged); 52 | } 53 | 54 | public CvarChanged(Handle:cvar, const String:oldVal[], const String:newVal[]) { 55 | GetConVarString(tagCvar, tag, sizeof(tag)); 56 | GetConVarString(messageBeginningCvar, messageBeginning, sizeof(messageBeginning)); 57 | GetConVarString(messageEndCvar, messageEnd, sizeof(messageEnd)); 58 | } 59 | 60 | public OnAllPluginsLoaded() { 61 | if(LibraryExists("updater")) { 62 | Updater_AddPlugin(UPDATE_URL); 63 | new String:newVersion[10]; 64 | Format(newVersion, sizeof(newVersion), "%sA", PLUGIN_VERSION); 65 | CreateConVar("sm_shutdown_countdown_version", newVersion, "Shutdown Countdown Version", FCVAR_DONTRECORD|FCVAR_NOTIFY); 66 | } else { 67 | CreateConVar("sm_shutdown_countdown_version", PLUGIN_VERSION, "Shutdown Countdown Version", FCVAR_DONTRECORD|FCVAR_NOTIFY); 68 | } 69 | } 70 | 71 | public Action:Command_ShutdownCountdown(client, args) { 72 | if(shutdownTimer != INVALID_HANDLE) { 73 | ReplyToCommand(client, "%s A shutdown countdown is already in progress.", tag); 74 | return Plugin_Handled; 75 | } 76 | if(shutdownTime != 0) { 77 | ReplyToCommand(client, "%s A shutdown countdown is already pending. Use sm_shutdown_confirm or sm_shutdown_cancel", tag); 78 | return Plugin_Handled; 79 | } 80 | if(args != 1) { 81 | ReplyToCommand(client, "%s Usage: sm_shutdown [time]", tag); 82 | return Plugin_Handled; 83 | } 84 | decl String:time[10]; 85 | GetCmdArg(1, time, sizeof(time)); 86 | if(!StringToIntEx(time, shutdownTime)) { 87 | ReplyToCommand(client, "%s Usage: sm_shutdown [time]", tag); 88 | return Plugin_Handled; 89 | } 90 | if(shutdownTime < 5) { 91 | ReplyToCommand(client, "%s The shutdown time must be greater than or equal to 5.", tag); 92 | return Plugin_Handled; 93 | } 94 | ReplyToCommand(client, "%s You requested a shutdown countdown for %i seconds. sm_shutdown_confirm = confirm, sm_shutdown_cancel = cancel.", tag, shutdownTime); 95 | LogAction(client, -1, "%L requested a server shutdown for %i seconds.", client, shutdownTime); 96 | return Plugin_Handled; 97 | } 98 | 99 | public Action:Command_ConfirmShutdown(client, args) { 100 | if(shutdownTime == 0) { 101 | ReplyToCommand(client, "%s You have not requested a shutdown countdown with sm_shutdown yet.", tag); 102 | return Plugin_Handled; 103 | } 104 | if(shutdownTimer != INVALID_HANDLE) { 105 | ReplyToCommand(client, "%s There is already a shutdown countdown running. Use sm_shutdown_cancel to cancel.", tag); 106 | return Plugin_Handled; 107 | } 108 | shutdownTimer = CreateTimer(1.0, Timer_Countdown, INVALID_HANDLE, TIMER_REPEAT); 109 | ReplyToCommand(client, "%s The timer has been started. Use sm_shutdown_cancel to cancel.", tag); 110 | LogAction(client, -1, "%L confirmed a server shutdown for %i seconds.", client, shutdownTime); 111 | return Plugin_Handled; 112 | } 113 | 114 | public Action:Command_CancelShutdown(client, args) { 115 | if(shutdownTime == 0) { 116 | ReplyToCommand(client, "%s You have not requested a shutdown countdown with sm_countdown yet.", tag); 117 | return Plugin_Handled; 118 | } 119 | if(shutdownTimer != INVALID_HANDLE) { 120 | KillTimer(shutdownTimer); 121 | PrintHintTextToAll("The shutdown has been cancelled."); 122 | } 123 | ReplyToCommand(client, "%s The shutdown request has been cancelled.", tag); 124 | if(shutdownTime <= GetConVarFloat(notifyCvar) && shutdownTimer != INVALID_HANDLE) { 125 | PrintCenterTextAll("The shutdown has been cancelled."); 126 | } 127 | shutdownTimer = INVALID_HANDLE; 128 | shutdownTime = 0; 129 | LogAction(client, -1, "%L cancelled a server shutdown.", client); 130 | return Plugin_Handled; 131 | } 132 | 133 | public Action:Timer_Countdown(Handle:timer) { 134 | PrintHintTextToAll("%s %i %s", messageBeginning, shutdownTime, messageEnd); 135 | if(shutdownTime <= GetConVarFloat(notifyCvar)) { 136 | PrintCenterTextAll("%s %i %s", messageBeginning, shutdownTime, messageEnd); 137 | PrintToServer("%s %i %s", messageBeginning, shutdownTime, messageEnd); 138 | } 139 | shutdownTime--; 140 | if(shutdownTime <= -1) { 141 | LogAction(-1, -1, "Server shutting down..."); 142 | KillTimer(shutdownTimer); 143 | ServerCommand("quit"); 144 | } 145 | } 146 | 147 | public Action:Updater_OnPluginDownloading() { 148 | if(!GetConVarBool(updaterCvar)) { 149 | return Plugin_Handled; 150 | } 151 | return Plugin_Continue; 152 | } 153 | 154 | public OnLibraryAdded(const String:name[]) { 155 | if(StrEqual(name, "updater")) { 156 | Updater_AddPlugin(UPDATE_URL); 157 | } 158 | } 159 | 160 | public Updater_OnPluginUpdated() { 161 | ReloadPlugin(); 162 | } -------------------------------------------------------------------------------- /scripting/st_gamedesc_override.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #undef REQUIRE_PLUGIN 7 | #include 8 | 9 | #define UPDATE_URL "http://hg.doctormckay.com/public-plugins/raw/default/game_desc_override.txt" 10 | #define PLUGIN_VERSION "1.1.3" 11 | 12 | new Handle:descriptionCvar = INVALID_HANDLE; 13 | new Handle:updaterCvar = INVALID_HANDLE; 14 | 15 | public Plugin:myinfo = { 16 | name = "[Any] SteamTools Game Description Override", 17 | author = "Dr. McKay", 18 | description = "Overrides the default game description (i.e. \"Team Fortress\") in the server browser using SteamTools", 19 | version = PLUGIN_VERSION, 20 | url = "http://www.doctormckay.com" 21 | }; 22 | 23 | public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) { 24 | MarkNativeAsOptional("Updater_AddPlugin"); 25 | return APLRes_Success; 26 | } 27 | 28 | public OnPluginStart() { 29 | descriptionCvar = CreateConVar("st_gamedesc_override", "", "What to override your game description to"); 30 | updaterCvar = CreateConVar("st_gamedesc_override_auto_update", "1", "Enables automatic updating. Has no effect if Updater is not installed."); 31 | decl String:description[128]; 32 | GetConVarString(descriptionCvar, description, sizeof(description)); 33 | HookConVarChange(descriptionCvar, CvarChanged); 34 | Steam_SetGameDescription(description); 35 | } 36 | 37 | public CvarChanged(Handle:cvar, const String:oldVal[], const String:newVal[]) { 38 | decl String:description[128]; 39 | GetConVarString(descriptionCvar, description, sizeof(description)); 40 | Steam_SetGameDescription(description); 41 | } 42 | 43 | public OnAllPluginsLoaded() { 44 | new Handle:buffer; 45 | if(LibraryExists("updater")) { 46 | Updater_AddPlugin(UPDATE_URL); 47 | new String:newVersion[10]; 48 | Format(newVersion, sizeof(newVersion), "%sA", PLUGIN_VERSION); 49 | buffer = CreateConVar("st_gamedesc_override_version", newVersion, "SteamTools Game Description Override Version", FCVAR_DONTRECORD|FCVAR_NOTIFY|FCVAR_CHEAT); 50 | } else { 51 | buffer = CreateConVar("st_gamedesc_override_version", PLUGIN_VERSION, "SteamTools Game Description Override Version", FCVAR_DONTRECORD|FCVAR_NOTIFY|FCVAR_CHEAT); 52 | } 53 | HookConVarChange(buffer, Callback_VersionConVarChanged); 54 | } 55 | 56 | public Callback_VersionConVarChanged(Handle:convar, const String:oldValue[], const String:newValue[]) { 57 | ResetConVar(convar); 58 | } 59 | 60 | public Action:Updater_OnPluginDownloading() { 61 | if(!GetConVarBool(updaterCvar)) { 62 | return Plugin_Handled; 63 | } 64 | return Plugin_Continue; 65 | } 66 | 67 | public OnLibraryAdded(const String:name[]) { 68 | if(StrEqual(name, "updater")) { 69 | Updater_AddPlugin(UPDATE_URL); 70 | } 71 | } 72 | 73 | public Updater_OnPluginUpdated() { 74 | ReloadPlugin(); 75 | } -------------------------------------------------------------------------------- /scripting/sticky_jumper_bombz.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #define PLUGIN_VERSION "1.1.1" 7 | #define WEAPON_JUMPER 265 8 | #define ATTRIBUTE_ADD_BOMBS 88 9 | #define ATTRIBUTE_MINUS_BOMBS 89 10 | 11 | public Plugin:myinfo = { 12 | name = "[TF2] Sticky Jumper Bombz", 13 | author = "Dr. McKay", 14 | description = "Allows you to customize the number of sticky jumper bombs that can be out", 15 | version = PLUGIN_VERSION, 16 | url = "http://www.doctormckay.com" 17 | }; 18 | 19 | new Handle:cvarMaxBombz; 20 | new Handle:newItem; 21 | 22 | #define UPDATE_FILE "sticky_jumper_bombz.txt" 23 | #define CONVAR_PREFIX "sticky_jumper" 24 | 25 | #include "mckayupdater.sp" 26 | 27 | public OnPluginStart() { 28 | cvarMaxBombz = CreateConVar("sticky_jumper_max_bombs", "2", "Maximum number of bombs that a player can lay out at once", _, true, 1.0); 29 | HookConVarChange(cvarMaxBombz, OnConVarChanged); 30 | } 31 | 32 | public OnConVarChanged(Handle:convar, const String:oldValue[], const String:newValue[]) { 33 | OnConfigsExecuted(); 34 | } 35 | 36 | public OnConfigsExecuted() { 37 | if(newItem != INVALID_HANDLE) { 38 | CloseHandle(newItem); 39 | } 40 | 41 | newItem = TF2Items_CreateItem(OVERRIDE_ATTRIBUTES|PRESERVE_ATTRIBUTES); 42 | 43 | new Float:diff = GetConVarFloat(cvarMaxBombz) - 8.0; 44 | if(diff <= 0.0) { 45 | TF2Items_SetAttribute(newItem, 0, ATTRIBUTE_MINUS_BOMBS, diff); 46 | TF2Items_SetNumAttributes(newItem, 1); 47 | } else { 48 | TF2Items_SetAttribute(newItem, 0, ATTRIBUTE_ADD_BOMBS, diff); 49 | TF2Items_SetAttribute(newItem, 1, ATTRIBUTE_MINUS_BOMBS, 0.0); 50 | TF2Items_SetNumAttributes(newItem, 2); 51 | } 52 | } 53 | 54 | public Action:TF2Items_OnGiveNamedItem(client, String:classname[], defindex, &Handle:item) { 55 | if(defindex == WEAPON_JUMPER && CheckCommandAccess(client, "sticky_jumper_bombz", 0, true)) { 56 | item = newItem; 57 | return Plugin_Changed; 58 | } 59 | 60 | return Plugin_Continue; 61 | } -------------------------------------------------------------------------------- /scripting/teamscores.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #undef REQUIRE_PLUGIN 7 | #include 8 | 9 | #define UPDATE_URL "http://hg.doctormckay.com/public-plugins/raw/default/teamscores.txt" 10 | #define PLUGIN_VERSION "1.3.1" 11 | 12 | new Handle:timeCvar = INVALID_HANDLE; 13 | new Handle:team2Cvar = INVALID_HANDLE; 14 | new Handle:team3Cvar = INVALID_HANDLE; 15 | new Handle:updaterCvar = INVALID_HANDLE; 16 | 17 | public Plugin:myinfo = { 18 | name = "[ANY] Team Scores", 19 | author = "Dr. McKay", 20 | description = "Sets team scores to a specified value at certain times, and on demand", 21 | version = PLUGIN_VERSION, 22 | url = "http://www.doctormckay.com" 23 | }; 24 | 25 | public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) { 26 | MarkNativeAsOptional("Updater_AddPlugin"); 27 | return APLRes_Success; 28 | } 29 | 30 | public OnPluginStart() { 31 | RegAdminCmd("sm_setscore", Command_SetScore, ADMFLAG_ROOT, "Usage: sm_setscore "); 32 | timeCvar = CreateConVar("teamscores_time", "1", "0 = never, 1 = on map start, 2 = on round start"); 33 | team2Cvar = CreateConVar("teamscores_team2", "37", "RED or Terrorists"); 34 | team3Cvar = CreateConVar("teamscores_team3", "13", "BLU or Counter-Terrorists"); 35 | updaterCvar = CreateConVar("teamscores_auto_update", "1", "Should automatic updating be enabled? Has no effect if Updater is not installed."); 36 | HookEventEx("teamplay_round_start", Event_RoundStart); 37 | HookEventEx("round_start", Event_RoundStart); 38 | } 39 | 40 | public OnAllPluginsLoaded() { 41 | if(LibraryExists("updater")) { 42 | Updater_AddPlugin(UPDATE_URL); 43 | new String:newVersion[10]; 44 | Format(newVersion, sizeof(newVersion), "%sA", PLUGIN_VERSION); 45 | CreateConVar("teamscores_version", newVersion, "Team Scores Version", FCVAR_DONTRECORD|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY); 46 | } else { 47 | CreateConVar("teamscores_version", PLUGIN_VERSION, "Team Scores Version", FCVAR_DONTRECORD|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY); 48 | } 49 | } 50 | 51 | public OnMapStart() { 52 | if(GetConVarInt(timeCvar) == 1) { 53 | SetScores(); 54 | } 55 | } 56 | 57 | public Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast) { 58 | if(GetConVarInt(timeCvar) == 2) { 59 | SetScores(); 60 | } 61 | } 62 | 63 | SetScores() { 64 | SetTeamScore(2, GetConVarInt(team2Cvar)); 65 | SetTeamScore(3, GetConVarInt(team3Cvar)); 66 | } 67 | 68 | public Action:Command_SetScore(client, args) { 69 | if(args != 2) { 70 | ReplyToCommand(client, "[SM] Usage: sm_setscore "); 71 | return Plugin_Handled; 72 | } 73 | new String:arg1[30]; 74 | new team; 75 | GetCmdArg(1, arg1, sizeof(arg1)); 76 | if(strcmp(arg1, "2") || strcmp(arg1, "3")) { 77 | team = StringToInt(arg1); 78 | } else { 79 | team = FindTeamByName(arg1); 80 | if(team != 2 && team != 3) { 81 | ReplyToCommand(client, "[SM] An invalid team name or index was specified."); 82 | return Plugin_Handled; 83 | } 84 | } 85 | new String:arg2[30]; 86 | new score; 87 | GetCmdArg(2, arg2, sizeof(arg2)); 88 | score = StringToInt(arg2); 89 | SetTeamScore(team, score); 90 | ReplyToCommand(client, "[SM] The score was set."); 91 | return Plugin_Handled; 92 | } 93 | 94 | public Action:Updater_OnPluginDownloading() { 95 | if(!GetConVarBool(updaterCvar)) { 96 | return Plugin_Handled; 97 | } 98 | return Plugin_Continue; 99 | } 100 | 101 | public OnLibraryAdded(const String:name[]) { 102 | if(StrEqual(name, "updater")) { 103 | Updater_AddPlugin(UPDATE_URL); 104 | } 105 | } 106 | 107 | public Updater_OnPluginUpdated() { 108 | ReloadPlugin(); 109 | } -------------------------------------------------------------------------------- /scripting/tidykick.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #undef REQUIRE_PLUGIN 8 | #include 9 | 10 | #define UPDATE_URL "http://hg.doctormckay.com/public-plugins/raw/default/tidykick.txt" 11 | #define PLUGIN_VERSION "1.1.5" 12 | 13 | public Plugin:myinfo = { 14 | name = "[ANY] Tidy Kick", 15 | author = "Dr. McKay", 16 | description = "Allows kick messages that aren't prefixed with Disconnect:", 17 | version = PLUGIN_VERSION, 18 | url = "http://www.doctormckay.com" 19 | }; 20 | 21 | new Handle:trie; 22 | new bool:kicked[MAXPLAYERS + 1]; 23 | new Handle:updaterCvar = INVALID_HANDLE; 24 | 25 | public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) { 26 | CreateNative("TidyKickClient", Native_TidyKick); 27 | MarkNativeAsOptional("Updater_AddPlugin"); 28 | return APLRes_Success; 29 | } 30 | 31 | public OnPluginStart() { 32 | updaterCvar = CreateConVar("tidykick_auto_update", "1", "Enables automatic updating (has no effect if Updater is not installed)"); 33 | trie = CreateTrie(); 34 | RegAdminCmd("sm_tidykick", Command_Kick, ADMFLAG_KICK, "Tidy kicks a client"); 35 | HookEvent("player_disconnect", Event_Disconnect, EventHookMode_Pre); 36 | LoadTranslations("common.phrases"); 37 | } 38 | 39 | public OnClientConnected(client) { 40 | kicked[client] = false; 41 | } 42 | 43 | public Action:Command_Kick(client, args) { 44 | if(args < 1) { 45 | ReplyToCommand(client, "[SM] Usage: sm_tidykick [reason]"); 46 | return Plugin_Handled; 47 | } 48 | decl String:argString[512]; 49 | GetCmdArgString(argString, sizeof(argString)); 50 | decl String:target[MAX_NAME_LENGTH]; 51 | new pos = BreakString(argString, target, sizeof(target)); 52 | new tgt = FindTarget(client, target, true); 53 | if(tgt == -1) { 54 | return Plugin_Handled; 55 | } 56 | if(pos == -1) { 57 | decl String:reason[255]; 58 | Format(reason, sizeof(reason), "%T", "Kicked by admin", tgt); 59 | DoKick(tgt, reason); 60 | } else { 61 | DoKick(tgt, argString[pos]); 62 | } 63 | return Plugin_Handled; 64 | } 65 | 66 | DoKick(target, const String:reason[255]) { 67 | decl String:auth[32]; 68 | GetClientAuthString(target, auth, sizeof(auth)); 69 | SetTrieString(trie, auth, reason); 70 | kicked[target] = true; 71 | CreateTimer(5.0, Timer_FallbackKick, GetClientUserId(target)); 72 | ClientCommand(target, "retry"); 73 | } 74 | 75 | public Action:Timer_FallbackKick(Handle:timer, any:userid) { 76 | new client = GetClientOfUserId(userid); 77 | if(client != 0) { 78 | decl String:auth[32], String:reason[255]; 79 | GetClientAuthString(client, auth, sizeof(auth)); 80 | if(GetTrieString(trie, auth, reason, sizeof(reason))) { 81 | KickClient(client, reason); 82 | RemoveFromTrie(trie, auth); 83 | } 84 | } 85 | } 86 | 87 | public bool:OnClientPreConnect(const String:name[], String:password[255], const String:ip[], const String:steamID[], String:rejectReason[255]) { 88 | decl String:reason[255]; 89 | if(!GetTrieString(trie, steamID, reason, sizeof(reason))) { 90 | return true; 91 | } 92 | StrCat(reason, sizeof(reason), "."); 93 | strcopy(rejectReason, sizeof(rejectReason), reason); 94 | RemoveFromTrie(trie, steamID); 95 | return false; 96 | } 97 | 98 | public Native_TidyKick(Handle:plugin, numParams) { 99 | // client, format, ... 100 | new client = GetNativeCell(1); 101 | if(client < 1 || client > MaxClients || !IsClientInGame(client)) { 102 | ThrowNativeError(1, "Client index %i is invalid or not in game", client); 103 | return; 104 | } 105 | decl String:reason[255]; 106 | new written; 107 | FormatNativeString(0, 2, 3, sizeof(reason), written, reason); 108 | DoKick(client, reason); 109 | } 110 | 111 | public Action:Event_Disconnect(Handle:event, const String:eventName[], bool:dontBroadcast) { 112 | new client = GetClientOfUserId(GetEventInt(event, "userid")); 113 | if(kicked[client]) { 114 | decl String:auth[32]; 115 | GetClientAuthString(client, auth, sizeof(auth)); 116 | decl String:reason[255]; 117 | GetTrieString(trie, auth, reason, sizeof(reason)); 118 | SetEventString(event, "reason", reason); 119 | kicked[client] = false; 120 | } 121 | } 122 | 123 | ///////////////////////////////// 124 | 125 | public OnAllPluginsLoaded() { 126 | new Handle:convar; 127 | if(LibraryExists("updater")) { 128 | Updater_AddPlugin(UPDATE_URL); 129 | new String:newVersion[10]; 130 | Format(newVersion, sizeof(newVersion), "%sA", PLUGIN_VERSION); 131 | convar = CreateConVar("tidykick_version", newVersion, "Tidy Kick Version", FCVAR_DONTRECORD|FCVAR_NOTIFY|FCVAR_CHEAT); 132 | } else { 133 | convar = CreateConVar("tidykick_version", PLUGIN_VERSION, "Tidy Kick Version", FCVAR_DONTRECORD|FCVAR_NOTIFY|FCVAR_CHEAT); 134 | } 135 | HookConVarChange(convar, Callback_VersionConVarChanged); 136 | } 137 | 138 | public Callback_VersionConVarChanged(Handle:convar, const String:oldValue[], const String:newValue[]) { 139 | ResetConVar(convar); 140 | } 141 | 142 | public Action:Updater_OnPluginDownloading() { 143 | if(!GetConVarBool(updaterCvar)) { 144 | return Plugin_Handled; 145 | } 146 | return Plugin_Continue; 147 | } 148 | 149 | public OnLibraryAdded(const String:name[]) { 150 | if(StrEqual(name, "updater")) { 151 | Updater_AddPlugin(UPDATE_URL); 152 | } 153 | } -------------------------------------------------------------------------------- /scripting/unrestricted_fov.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #undef REQUIRE_EXTENSIONS 9 | #include 10 | 11 | #define PLUGIN_VERSION "1.2.0" 12 | 13 | public Plugin:myinfo = { 14 | name = "[ANY] Unrestricted FOV", 15 | author = "Dr. McKay", 16 | description = "Allows players to choose their own FOV", 17 | version = PLUGIN_VERSION, 18 | url = "http://www.doctormckay.com" 19 | }; 20 | 21 | new Handle:cookieFOV; 22 | new Handle:cvarFOVMin; 23 | new Handle:cvarFOVMax; 24 | 25 | #define UPDATE_FILE "unrestricted_fov.txt" 26 | #define CONVAR_PREFIX "ufov" 27 | #include "mckayupdater.sp" 28 | 29 | public OnPluginStart() { 30 | cookieFOV = RegClientCookie("unrestricted_fov", "Client Desired FOV", CookieAccess_Private); 31 | 32 | cvarFOVMin = CreateConVar("ufov_min", "20", "Minimum FOV a client can set with the !fov command", _, true, 20.0, true, 180.0); 33 | cvarFOVMax = CreateConVar("ufov_max", "130", "Maximum FOV a client can set with the !fov command", _, true, 20.0, true, 180.0); 34 | 35 | RegEasyConCmd("sm_fov ", Command_FOV, {Cmd_Cell}, 1, 0); 36 | HookEvent("player_spawn", Event_PlayerSpawn); 37 | } 38 | 39 | public Command_FOV(client, fov) { 40 | if(!AreClientCookiesCached(client)) { 41 | ReplyToCommand(client, "\x04[SM] \x01This command is currently unavailable. Please try again later."); 42 | return; 43 | } 44 | if(fov == 0) { 45 | QueryClientConVar(client, "fov_desired", OnFOVQueried); 46 | ReplyToCommand(client, "\x04[SM] \x01Your FOV has been reset."); 47 | return; 48 | } 49 | if(fov < GetConVarInt(cvarFOVMin)) { 50 | QueryClientConVar(client, "fov_desired", OnFOVQueried); 51 | ReplyToCommand(client, "\x04[SM] \x01The minimum FOV you can set with !fov is %d.", GetConVarInt(cvarFOVMin)); 52 | return; 53 | } 54 | if(fov > GetConVarInt(cvarFOVMax)) { 55 | QueryClientConVar(client, "fov_desired", OnFOVQueried); 56 | ReplyToCommand(client, "\x04[SM] \x01The maximum FOV you can set with !fov is %d.", GetConVarInt(cvarFOVMax)); 57 | return; 58 | } 59 | decl String:cookie[12]; 60 | IntToString(fov, cookie, sizeof(cookie)); 61 | SetClientCookie(client, cookieFOV, cookie); 62 | 63 | SetEntProp(client, Prop_Send, "m_iFOV", fov); 64 | SetEntProp(client, Prop_Send, "m_iDefaultFOV", fov); 65 | 66 | ReplyToCommand(client, "\x04[SM] \x01Your FOV has been set to %d on this server.", fov); 67 | } 68 | 69 | public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) { 70 | new client = GetClientOfUserId(GetEventInt(event, "userid")); 71 | if(!AreClientCookiesCached(client)) { 72 | return; 73 | } 74 | 75 | decl String:cookie[12]; 76 | GetClientCookie(client, cookieFOV, cookie, sizeof(cookie)); 77 | new fov = StringToInt(cookie); 78 | if(fov < GetConVarInt(cvarFOVMin) || fov > GetConVarInt(cvarFOVMax)) { 79 | return; 80 | } 81 | SetEntProp(client, Prop_Send, "m_iFOV", fov); 82 | SetEntProp(client, Prop_Send, "m_iDefaultFOV", fov); 83 | } 84 | 85 | public TF2_OnConditionAdded(client, TFCond:condition) { 86 | if(condition != TFCond_TeleportedGlow) { 87 | return; 88 | } 89 | decl String:cookie[12]; 90 | GetClientCookie(client, cookieFOV, cookie, sizeof(cookie)); 91 | new fov = StringToInt(cookie); 92 | if(fov < GetConVarInt(cvarFOVMin) || fov > GetConVarInt(cvarFOVMax)) { 93 | return; 94 | } 95 | SetEntProp(client, Prop_Send, "m_iFOV", fov); 96 | SetEntProp(client, Prop_Send, "m_iDefaultFOV", fov); 97 | } 98 | 99 | public TF2_OnConditionRemoved(client, TFCond:condition) { 100 | if(condition != TFCond_Zoomed) { 101 | return; 102 | } 103 | decl String:cookie[12]; 104 | GetClientCookie(client, cookieFOV, cookie, sizeof(cookie)); 105 | new fov = StringToInt(cookie); 106 | if(fov < GetConVarInt(cvarFOVMin) || fov > GetConVarInt(cvarFOVMax)) { 107 | return; 108 | } 109 | SetEntProp(client, Prop_Send, "m_iFOV", fov); 110 | SetEntProp(client, Prop_Send, "m_iDefaultFOV", fov); 111 | } 112 | 113 | public OnFOVQueried(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[]) { 114 | if(result != ConVarQuery_Okay) { 115 | return; 116 | } 117 | SetClientCookie(client, cookieFOV, ""); 118 | SetEntProp(client, Prop_Send, "m_iFOV", StringToInt(cvarValue)); 119 | SetEntProp(client, Prop_Send, "m_iDefaultFOV", StringToInt(cvarValue)); 120 | } -------------------------------------------------------------------------------- /scripting/votekick_switcher.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | 5 | #define PLUGIN_VERSION "1.3.0" 6 | 7 | new Handle:cvarVotekick; 8 | new Handle:cvarVotekickMvM; 9 | 10 | public Plugin:myinfo = { 11 | name = "[TF2/CS:GO] Votekick Switcher", 12 | author = "Dr. McKay", 13 | description = "Disables the built-in votekick when there are admins present", 14 | version = PLUGIN_VERSION, 15 | url = "http://www.doctormckay.com" 16 | }; 17 | 18 | #define UPDATE_FILE "votekick_switcher.txt" 19 | #define CONVAR_PREFIX "votekick_switcher" 20 | #define RELOAD_ON_UPDATE 21 | 22 | #include "mckayupdater.sp" 23 | 24 | public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) { 25 | MarkNativeAsOptional("Updater_AddPlugin"); 26 | 27 | cvarVotekick = FindConVar("sv_vote_issue_kick_allowed"); 28 | cvarVotekickMvM = FindConVar("sv_vote_issue_kick_allowed_mvm"); 29 | 30 | if(cvarVotekick == INVALID_HANDLE) { 31 | strcopy(error, err_max, "sv_vote_issue_kick_allowed cvar not found"); 32 | return APLRes_Failure; 33 | } 34 | 35 | return APLRes_Success; 36 | } 37 | 38 | public OnPluginStart() { 39 | new Handle:sv_allow_votes = FindConVar("sv_allow_votes"); 40 | if(sv_allow_votes != INVALID_HANDLE && !GetConVarBool(sv_allow_votes)) { 41 | LogError("WARNING: sv_allow_votes is set to 0, so no players will be able to call votes regardless of sv_vote_issue_kick_allowed!"); 42 | } 43 | } 44 | 45 | public OnMapStart() { 46 | CheckAdmins(); 47 | } 48 | 49 | public OnClientPostAdminCheck(client) { 50 | if(CheckCommandAccess(client, "sm_kick", ADMFLAG_KICK)) { 51 | SetConVarBool(cvarVotekick, false); 52 | 53 | if(cvarVotekickMvM != INVALID_HANDLE) { 54 | SetConVarBool(cvarVotekickMvM, false); 55 | } 56 | } 57 | } 58 | 59 | public OnClientDisconnect(client) { 60 | CheckAdmins(); 61 | } 62 | 63 | CheckAdmins() { 64 | new bool:newState = true; 65 | for(new i = 1; i <= MaxClients; i++) { 66 | if(IsClientInGame(i) && CheckCommandAccess(i, "sm_kick", ADMFLAG_KICK)) { 67 | newState = false; 68 | break; 69 | } 70 | } 71 | SetConVarBool(cvarVotekick, newState); 72 | 73 | if(cvarVotekickMvM != INVALID_HANDLE) { 74 | SetConVarBool(cvarVotekickMvM, newState); 75 | } 76 | } -------------------------------------------------------------------------------- /scripting/votescramble.sp: -------------------------------------------------------------------------------- 1 | #pragma semicolon 1 2 | 3 | #include 4 | #include 5 | 6 | #define PLUGIN_VERSION "1.2.0" 7 | 8 | public Plugin:myinfo = { 9 | name = "[TF2] Better Vote Scramble", 10 | author = "Dr. McKay", 11 | description = "A vote scramble system that uses TF2's built-in scrambler when the next round begins", 12 | version = PLUGIN_VERSION, 13 | url = "http://www.doctormckay.com" 14 | } 15 | 16 | new Handle:cvarPercentage; 17 | new Handle:cvarVotesRequired; 18 | 19 | new bool:votedToScramble[MAXPLAYERS + 1]; 20 | new bool:scrambleTeams = false; 21 | 22 | new Handle:mp_bonusroundtime; 23 | 24 | #define UPDATE_FILE "votescramble.txt" 25 | #define CONVAR_PREFIX "better_votescramble" 26 | 27 | #include "mckayupdater.sp" 28 | 29 | public OnPluginStart() { 30 | cvarPercentage = CreateConVar("better_votescramble_percentage", "0.6", "Percentage required to initiate a team scramble"); 31 | cvarVotesRequired = CreateConVar("better_votescramble_votes_required", "3", "Votes required to initiate a vote"); 32 | 33 | AddCommandListener(Command_Say, "say"); 34 | AddCommandListener(Command_Say, "say_team"); 35 | 36 | HookEvent("teamplay_round_win", Event_RoundEnd); 37 | HookEvent("teamplay_round_stalemate", Event_RoundEnd); 38 | HookEvent("teamplay_win_panel", Event_RoundEnd); 39 | 40 | mp_bonusroundtime = FindConVar("mp_bonusroundtime"); 41 | 42 | LoadTranslations("core.phrases"); 43 | } 44 | 45 | public OnClientConnected(client) { 46 | votedToScramble[client] = false; 47 | } 48 | 49 | public Action:Command_Say(client, const String:command[], argc) { 50 | decl String:message[256]; 51 | GetCmdArgString(message, sizeof(message)); 52 | StripQuotes(message); 53 | TrimString(message); 54 | if(!StrEqual(message, "votescramble", false) && !StrEqual(message, "!votescramble", false)) { 55 | return Plugin_Continue; 56 | } 57 | if(!CheckCommandAccess(client, "votescramble", 0)) { 58 | ReplyToCommand(client, "[SM] %t.", "No Access"); 59 | return Plugin_Continue; 60 | } 61 | if(votedToScramble[client]) { 62 | PrintToChatDelay(client, "\x04[SM] \x01You have already voted to scramble the teams."); 63 | return Plugin_Continue; 64 | } 65 | if(IsVoteInProgress()) { 66 | PrintToChatDelay(client, "\x04[SM] \x01Please wait for the current vote to end."); 67 | return Plugin_Continue; 68 | } 69 | if(scrambleTeams) { 70 | PrintToChatDelay(client, "\x04[SM] \x01A previous scramble vote has succeeded. Teams will be scrambled when the round ends."); 71 | return Plugin_Continue; 72 | } 73 | votedToScramble[client] = true; 74 | PrintToChatAllDelay(client, "{green}[SM] {teamcolor}%N {default}has voted to scramble the teams. [{lightgreen}%i{default}/{lightgreen}%i {default}votes required]", client, GetTotalVotes(), GetConVarInt(cvarVotesRequired)); 75 | if(GetTotalVotes() >= GetConVarInt(cvarVotesRequired)) { 76 | InitiateVote(); 77 | } 78 | return Plugin_Continue; 79 | } 80 | 81 | PrintToChatDelay(client, const String:format[], any:...) { 82 | decl String:buffer[512]; 83 | VFormat(buffer, sizeof(buffer), format, 3); 84 | new Handle:pack = CreateDataPack(); 85 | WritePackCell(pack, GetClientUserId(client)); 86 | WritePackString(pack, buffer); 87 | CreateTimer(0.0, Timer_PrintToChat, pack); 88 | } 89 | 90 | PrintToChatAllDelay(client, const String:format[], any:...) { 91 | decl String:buffer[512]; 92 | VFormat(buffer, sizeof(buffer), format, 3); 93 | new Handle:pack = CreateDataPack(); 94 | WritePackCell(pack, GetClientUserId(client)); 95 | WritePackString(pack, buffer); 96 | CreateTimer(0.0, Timer_PrintToChatAll, pack); 97 | } 98 | 99 | public Action:Timer_PrintToChat(Handle:timer, any:pack) { 100 | ResetPack(pack); 101 | new client = GetClientOfUserId(ReadPackCell(pack)); 102 | if(client == 0) { 103 | CloseHandle(pack); 104 | return; 105 | } 106 | decl String:message[512]; 107 | ReadPackString(pack, message, sizeof(message)); 108 | CloseHandle(pack); 109 | PrintToChat(client, message); 110 | } 111 | 112 | public Action:Timer_PrintToChatAll(Handle:timer, any:pack) { 113 | ResetPack(pack); 114 | new client = GetClientOfUserId(ReadPackCell(pack)); 115 | if(client == 0) { 116 | CloseHandle(pack); 117 | return; 118 | } 119 | decl String:message[512]; 120 | ReadPackString(pack, message, sizeof(message)); 121 | CloseHandle(pack); 122 | CPrintToChatAllEx(client, message); 123 | } 124 | 125 | GetTotalVotes() { 126 | new total = 0; 127 | for(new i = 1; i <= MaxClients; i++) { 128 | if(IsClientInGame(i) && !IsFakeClient(i) && votedToScramble[i]) { 129 | total++; 130 | } 131 | } 132 | return total; 133 | } 134 | 135 | InitiateVote() { 136 | for(new i = 1; i <= MaxClients; i++) { 137 | votedToScramble[i] = false; 138 | } 139 | new Handle:menu = CreateMenu(Handler_CastVote); 140 | SetMenuTitle(menu, "Scramble teams at the end of the round?"); 141 | AddMenuItem(menu, "yes", "Yes"); 142 | AddMenuItem(menu, "no", "No"); 143 | SetMenuExitButton(menu, false); 144 | VoteMenuToAll(menu, 20); 145 | } 146 | 147 | public Handler_CastVote(Handle:menu, MenuAction:action, param1, param2) { 148 | if(action == MenuAction_End) { 149 | CloseHandle(menu); 150 | } else if(action == MenuAction_VoteCancel && param1 == VoteCancel_NoVotes) { 151 | PrintToChatAll("\x04[SM] \x01Team scramble vote failed: no votes were cast."); 152 | } else if(action == MenuAction_VoteEnd) { 153 | decl String:item[64]; 154 | new Float:percent, Float:limit, votes, totalVotes; 155 | 156 | GetMenuVoteInfo(param2, votes, totalVotes); 157 | GetMenuItem(menu, param1, item, sizeof(item)); 158 | 159 | percent = FloatDiv(float(votes),float(totalVotes)); 160 | limit = GetConVarFloat(cvarPercentage); 161 | 162 | if(FloatCompare(percent, limit) >= 0 && StrEqual(item, "yes")) { 163 | PrintToChatAll("\x04[SM] \x01The vote was successful. Teams will be scrambled at the start of the next round."); 164 | scrambleTeams = true; 165 | } else { 166 | PrintToChatAll("\x04[SM] \x01The vote failed."); 167 | } 168 | } 169 | } 170 | 171 | public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) { 172 | if(scrambleTeams) { 173 | new Float:delay = GetConVarFloat(mp_bonusroundtime) - 7.0; 174 | if(delay < 0.0) { 175 | delay = 0.0; 176 | } 177 | 178 | scrambleTeams = false; 179 | CreateTimer(delay, Timer_Scramble); 180 | } 181 | } 182 | 183 | public Action:Timer_Scramble(Handle:timer) { 184 | ServerCommand("mp_scrambleteams 2"); 185 | PrintToChatAll("\x04[SM] \x01Scrambling the teams due to vote."); 186 | } -------------------------------------------------------------------------------- /short_circuit_nerf.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.0.2" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Fixed an error" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/short_circuit_nerf.smx" 17 | "Source" "Path_SM/scripting/short_circuit_nerf.sp" 18 | "Source" "Path_SM/scripting/mckayupdater.sp" 19 | } 20 | } -------------------------------------------------------------------------------- /shutdowncountdown.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.6.2" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Updater improvements" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/shutdowncountdown.smx" 17 | "Source" "Path_SM/scripting/shutdowncountdown.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /smac-autodemo.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.2.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - sourcemod/smac_recording.cfg is now executed when a demo recording starts" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/smac_autodemo.smx" 17 | "Source" "Path_SM/scripting/smac_autodemo.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /smdj_version.txt: -------------------------------------------------------------------------------- 1 | 2.3.0 -------------------------------------------------------------------------------- /steamrep.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.2.0" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Added support for SourceBans 1.5/2.0 plugin" 11 | "Notes" " - Switched from deprecated CCC_OnTagApplied to CCC_OnColor forward" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/steamrep_checker.smx" 17 | "Source" "Path_SM/scripting/steamrep_checker.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /sticky_jumper_bombz.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.1.1" 8 | } 9 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 10 | "Notes" " - Fixed issue where stickybombs would appear as normal bombs" 11 | "Notes" " - Removed artificial 10-bomb limit" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/sticky_jumper_bombz.smx" 17 | "Source" "Path_SM/scripting/sticky_jumper_bombz.sp" 18 | "Source" "Path_SM/scripting/mckayupdater.sp" 19 | } 20 | } -------------------------------------------------------------------------------- /teamscores.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.3.1" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Updater improvements" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/teamscores.smx" 17 | "Source" "Path_SM/scripting/teamscores.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /tidykick.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.1.5" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Updater improvements" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/tidykick.smx" 17 | "Source" "Path_SM/scripting/tidykick.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /translations/backpack-tf.phrases.txt: -------------------------------------------------------------------------------- 1 | "Phrases" 2 | { 3 | "Price list updated" 4 | { 5 | "en" "Price list updated." 6 | } 7 | "Type !pc for a price check" 8 | { 9 | "en" "Type !pc for a price check." 10 | } 11 | "Up" 12 | { 13 | "en" "Up" 14 | } 15 | "Down" 16 | { 17 | "en" "Down" 18 | } 19 | "From" 20 | { 21 | "en" "from" 22 | } 23 | "To" 24 | { 25 | "en" "to" 26 | } 27 | "Price check" 28 | { 29 | "#format" "{1:s}" 30 | "en" "Price check: {1}" 31 | } 32 | "Prices are estimates only" 33 | { 34 | "en" "Prices are estimates only" 35 | } 36 | "Prices courtesy of backpack.tf" 37 | { 38 | "en" "Prices courtesy of backpack.tf" 39 | } 40 | "Please allow backpack.tf time to load" 41 | { 42 | "en" "Please allow backpack.tf time to load" 43 | } 44 | "The price list has not loaded yet" 45 | { 46 | "en" "The price list has not loaded yet" 47 | } 48 | } -------------------------------------------------------------------------------- /translations/da/backpack-tf.phrases.txt: -------------------------------------------------------------------------------- 1 | // Exported from SourceMod Translator 2 | // Date: 2013-10-23 20:49:22 UTC 3 | // Language: Danish (da) 4 | // 5 | // To view other translations for this plugin, please visit: 6 | // http://translator.mitchdempsey.com/sourcemod_plugins/122 7 | // 8 | "Phrases" 9 | { 10 | 11 | "From" 12 | { 13 | "da" "fra" 14 | } 15 | 16 | "Down" 17 | { 18 | "da" "Ned" 19 | } 20 | 21 | "Prices are estimates only" 22 | { 23 | "da" "Priser er kun cirka priser" 24 | } 25 | 26 | "Prices courtesy of backpack.tf" 27 | { 28 | "da" "Priser takket vær backpack.tf" 29 | } 30 | 31 | "To" 32 | { 33 | "da" "til" 34 | } 35 | 36 | "Price list updated" 37 | { 38 | "da" "Pris liste opdateret" 39 | } 40 | 41 | "Price check" 42 | { 43 | "da" "Pris tjek: {1}" 44 | } 45 | 46 | "The price list has not loaded yet" 47 | { 48 | "da" "Pris listen er ikke blevet indlæst endnu" 49 | } 50 | 51 | "Up" 52 | { 53 | "da" "Op" 54 | } 55 | 56 | "Please allow backpack.tf time to load" 57 | { 58 | "da" "GIv venligst backpack.tf tid til at indlæse" 59 | } 60 | 61 | "Type !pc for a price check" 62 | { 63 | "da" "Skriv !pc for at lave et pris tjek." 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /translations/de/backpack-tf.phrases.txt: -------------------------------------------------------------------------------- 1 | // Exported from SourceMod Translator 2 | // Date: 2013-10-23 20:49:22 UTC 3 | // Language: German (de) 4 | // 5 | // To view other translations for this plugin, please visit: 6 | // http://translator.mitchdempsey.com/sourcemod_plugins/122 7 | // 8 | "Phrases" 9 | { 10 | 11 | "To" 12 | { 13 | "de" "zu" 14 | } 15 | 16 | "Down" 17 | { 18 | "de" "Unten" 19 | } 20 | 21 | "Type !pc for a price check" 22 | { 23 | "de" "Benutze !pc für einen Preischeck." 24 | } 25 | 26 | "Price check" 27 | { 28 | "de" "Preischeck: {1}" 29 | } 30 | 31 | "Up" 32 | { 33 | "de" "Gestiegen" 34 | } 35 | 36 | "Please allow backpack.tf time to load" 37 | { 38 | "de" "Lass bitte backpack.tf Zeit zum Laden." 39 | } 40 | 41 | "From" 42 | { 43 | "de" "von" 44 | } 45 | 46 | "Price list updated" 47 | { 48 | "de" "Preisliste erneuert." 49 | } 50 | 51 | "The price list has not loaded yet" 52 | { 53 | "de" "Die Preisliste wurde noch nicht geladen." 54 | } 55 | 56 | "Prices courtesy of backpack.tf" 57 | { 58 | "de" "Preise in Verbindung von backpack.tf" 59 | } 60 | 61 | "Prices are estimates only" 62 | { 63 | "de" "Preise wurden nur geschätzt." 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /translations/es/backpack-tf.phrases.txt: -------------------------------------------------------------------------------- 1 | // Exported from SourceMod Translator 2 | // Date: 2013-10-23 20:49:22 UTC 3 | // Language: Spanish (es) 4 | // 5 | // To view other translations for this plugin, please visit: 6 | // http://translator.mitchdempsey.com/sourcemod_plugins/122 7 | // 8 | "Phrases" 9 | { 10 | 11 | "Up" 12 | { 13 | "es" "Arriba" 14 | } 15 | 16 | "Down" 17 | { 18 | "es" "Abajo" 19 | } 20 | 21 | "The price list has not loaded yet" 22 | { 23 | "es" "La lista de precios no se ha cargado aun" 24 | } 25 | 26 | "Price check" 27 | { 28 | "es" "Precio: {1}" 29 | } 30 | 31 | "Price list updated" 32 | { 33 | "es" "Lista de precios actualizada." 34 | } 35 | 36 | "Type !pc for a price check" 37 | { 38 | "es" "Escribe !pc para comprobar un precio." 39 | } 40 | 41 | "Prices courtesy of backpack.tf" 42 | { 43 | "es" "Precios por cortesia de backpack.tf" 44 | } 45 | 46 | "Please allow backpack.tf time to load" 47 | { 48 | "es" "Por favor, dale tiempo a backpack.tf para que cargue" 49 | } 50 | 51 | "From" 52 | { 53 | "es" "desde" 54 | } 55 | 56 | "To" 57 | { 58 | "es" "hasta" 59 | } 60 | 61 | "Prices are estimates only" 62 | { 63 | "es" "Los precios son solo estimaciones" 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /translations/nl/backpack-tf.phrases.txt: -------------------------------------------------------------------------------- 1 | // Exported from SourceMod Translator 2 | // Date: 2013-10-23 20:49:22 UTC 3 | // Language: Dutch (nl) 4 | // 5 | // To view other translations for this plugin, please visit: 6 | // http://translator.mitchdempsey.com/sourcemod_plugins/122 7 | // 8 | "Phrases" 9 | { 10 | 11 | "Prices are estimates only" 12 | { 13 | "nl" "Prijzen zijn slechts schattingen" 14 | } 15 | 16 | "To" 17 | { 18 | "nl" "om" 19 | } 20 | 21 | "From" 22 | { 23 | "nl" "van" 24 | } 25 | 26 | "Type !pc for a price check" 27 | { 28 | "nl" "Schrijf !pc voor een prijsaanvraag." 29 | } 30 | 31 | "The price list has not loaded yet" 32 | { 33 | "nl" "De prijslijst is nog niet geladen" 34 | } 35 | 36 | "Down" 37 | { 38 | "nl" "Af" 39 | } 40 | 41 | "Prices courtesy of backpack.tf" 42 | { 43 | "nl" "Prijzen volgens backpack.tf" 44 | } 45 | 46 | "Price list updated" 47 | { 48 | "nl" "Prijslijst bijgewerkt." 49 | } 50 | 51 | "Up" 52 | { 53 | "nl" "Actief" 54 | } 55 | 56 | "Please allow backpack.tf time to load" 57 | { 58 | "nl" "Gelieve backpack.tf de tijd te geven om te laden" 59 | } 60 | 61 | "Price check" 62 | { 63 | "nl" "Prijs controle: {1}" 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /translations/pl/backpack-tf.phrases.txt: -------------------------------------------------------------------------------- 1 | // Exported from SourceMod Translator 2 | // Date: 2013-10-23 20:49:22 UTC 3 | // Language: Polish (pl) 4 | // 5 | // To view other translations for this plugin, please visit: 6 | // http://translator.mitchdempsey.com/sourcemod_plugins/122 7 | // 8 | "Phrases" 9 | { 10 | 11 | "Price list updated" 12 | { 13 | "pl" "Cennik zaktualizowany." 14 | } 15 | 16 | "Type !pc for a price check" 17 | { 18 | "pl" "Wpisz !pc aby otworzyć cennik." 19 | } 20 | 21 | "Up" 22 | { 23 | "pl" "Wzrost" 24 | } 25 | 26 | "Down" 27 | { 28 | "pl" "Spadek" 29 | } 30 | 31 | "From" 32 | { 33 | "pl" "z" 34 | } 35 | 36 | "To" 37 | { 38 | "pl" "na" 39 | } 40 | 41 | "Price check" 42 | { 43 | "pl" "Przedmiot: {1}" 44 | } 45 | 46 | "Prices are estimates only" 47 | { 48 | "pl" "Są to tylko ceny sugerowane" 49 | } 50 | 51 | "Prices courtesy of backpack.tf" 52 | { 53 | "pl" "Pochodzą ze strony backpack.tf" 54 | } 55 | 56 | "Please allow backpack.tf time to load" 57 | { 58 | "pl" "Poczekaj na załadowanie się backpack.tf" 59 | } 60 | 61 | "The price list has not loaded yet" 62 | { 63 | "pl" "Cennik nie został jeszcze załadowany" 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /translations/ru/backpack-tf.phrases.txt: -------------------------------------------------------------------------------- 1 | // Exported from SourceMod Translator 2 | // Date: 2013-10-23 20:49:22 UTC 3 | // Language: Russian (ru) 4 | // 5 | // To view other translations for this plugin, please visit: 6 | // http://translator.mitchdempsey.com/sourcemod_plugins/122 7 | // 8 | "Phrases" 9 | { 10 | 11 | "Up" 12 | { 13 | "ru" "Вверх" 14 | } 15 | 16 | "Price list updated" 17 | { 18 | "ru" "Список цен обновлен." 19 | } 20 | 21 | "Type !pc for a price check" 22 | { 23 | "ru" "Введите !pc для просмотра цен." 24 | } 25 | 26 | "Price check" 27 | { 28 | "ru" "Предмет: {1}" 29 | } 30 | 31 | "Prices courtesy of backpack.tf" 32 | { 33 | "ru" "Цены предоставлены сайтом backpack.tf" 34 | } 35 | 36 | "Down" 37 | { 38 | "ru" "Вниз" 39 | } 40 | 41 | "The price list has not loaded yet" 42 | { 43 | "ru" "Список цен не загружен" 44 | } 45 | 46 | "Please allow backpack.tf time to load" 47 | { 48 | "ru" "Пожалуйста, дождитесь загрузки backpack.tf" 49 | } 50 | 51 | "From" 52 | { 53 | "ru" "из" 54 | } 55 | 56 | "Prices are estimates only" 57 | { 58 | "ru" "Цены являются ориентировочными" 59 | } 60 | 61 | "To" 62 | { 63 | "ru" "для" 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /unrestricted_fov.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.2.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Custom FOV is no longer reset after teleporting" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/unrestricted_fov.smx" 17 | "Source" "Path_SM/scripting/unrestricted_fov.sp" 18 | } 19 | } -------------------------------------------------------------------------------- /votekick_switcher.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.3.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Added support for CS:GO" 12 | "Notes" " - Updater improvements" 13 | } 14 | 15 | "Files" 16 | { 17 | "Plugin" "Path_SM/plugins/votekick_switcher.smx" 18 | "Source" "Path_SM/scripting/votekick_switcher.sp" 19 | } 20 | } -------------------------------------------------------------------------------- /votescramble.txt: -------------------------------------------------------------------------------- 1 | "Updater" 2 | { 3 | "Information" 4 | { 5 | "Version" 6 | { 7 | "Latest" "1.2.0" 8 | } 9 | 10 | "Notes" "Find a list of my plugins (and links to their threads) at www.doctormckay.com. Changes:" 11 | "Notes" " - Moved scramble time to end of the round instead of the start of the next one, to prevent the round from starting twice" 12 | } 13 | 14 | "Files" 15 | { 16 | "Plugin" "Path_SM/plugins/votescramble.smx" 17 | "Source" "Path_SM/scripting/votescramble.sp" 18 | } 19 | } --------------------------------------------------------------------------------