Advertisement
Guest User

Untitled

a guest
Feb 27th, 2020
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 131.90 KB | None | 0 0
  1. // *********************************************************************************
  2. // PREPROCESSOR
  3. // *********************************************************************************
  4. #pragma semicolon 1 // Force strict semicolon mode.
  5.  
  6. // *********************************************************************************
  7. // INCLUDES
  8. // *********************************************************************************
  9. #include <sourcemod>
  10. #include <sdktools>
  11. #include <sdkhooks>
  12. #include <tf2>
  13. #include <tf2_stocks>
  14. #include <tf2items>
  15. #include <tf2attributes>
  16. #include <morecolors>
  17.  
  18.  
  19. // *********************************************************************************
  20. // CONSTANTS
  21. // *********************************************************************************
  22. // ---- Plugin-related constants ---------------------------------------------------
  23. #define PLUGIN_NAME "[TF2] Zonas' Custom Dodgeball Plugin"
  24. #define PLUGIN_AUTHOR "Damizean, Edited by blood and soul, Modifications from Walgrim's, edit combined by DeadSworn"
  25. #define PLUGIN_VERSION "2.0 - Mod"
  26. #define PLUGIN_CONTACT "https://savita-gaming.com"
  27.  
  28. // ---- General settings -----------------------------------------------------------
  29.  
  30. #define FPS_LOGIC_RATE 20.0
  31. #define FPS_LOGIC_INTERVAL 1.0 / FPS_LOGIC_RATE
  32.  
  33. // ---- Maximum structure sizes ----------------------------------------------------
  34. #define MAX_ROCKETS 100
  35. #define MAX_ROCKET_CLASSES 50
  36. #define MAX_SPAWNER_CLASSES 50
  37. #define MAX_SPAWN_POINTS 100
  38.  
  39. // ---- 1V1 ------------------------------------------------------------------------
  40.  
  41. #define TEAM_RED 2
  42. #define TEAM_BLUE 3
  43.  
  44. // ---- PyroVision Stuff -----------------------------------------------------------
  45. #define PYROVISION_ATTRIBUTE "vision opt in flags"
  46.  
  47. #define USAGE "Usage: sm_ab [0/1]"
  48. int abPrevention[MAXPLAYERS + 1];
  49. int firstJoined[MAXPLAYERS + 1];
  50.  
  51. // ---- Asherkin's RocketBounce Stuff ----------------------------------------------
  52. #define MAX_EDICT_BITS 11
  53. #define MAX_EDICTS (1 << MAX_EDICT_BITS)
  54.  
  55. int g_nBounces[MAX_EDICTS];
  56.  
  57. Handle g_hMaxBouncesConVar;
  58. int g_config_iMaxBounces = 2;
  59.  
  60. // ---- Airblast -------------------------------------------------------------------
  61. bool Airblast[MAXPLAYERS + 1] = { true, ... };
  62.  
  63. // Particlessss
  64. //int g_RocketParticle[MAXPLAYERS + 1];
  65.  
  66. // ---- Flags and types constants --------------------------------------------------
  67. enum Musics
  68. {
  69. Music_RoundStart,
  70. Music_RoundWin,
  71. Music_RoundLose,
  72. Music_Gameplay,
  73. SizeOfMusicsArray
  74. };
  75.  
  76.  
  77. enum BehaviourTypes
  78. {
  79. Behaviour_Unknown,
  80. Behaviour_Homing
  81. };
  82.  
  83. enum RocketFlags
  84. {
  85. RocketFlag_None = 0,
  86. RocketFlag_PlaySpawnSound = 1 << 0,
  87. RocketFlag_PlayBeepSound = 1 << 1,
  88. RocketFlag_PlayAlertSound = 1 << 2,
  89. RocketFlag_ElevateOnDeflect = 1 << 3,
  90. RocketFlag_IsNeutral = 1 << 4,
  91. RocketFlag_Exploded = 1 << 5,
  92. RocketFlag_OnSpawnCmd = 1 << 6,
  93. RocketFlag_OnDeflectCmd = 1 << 7,
  94. RocketFlag_OnKillCmd = 1 << 8,
  95. RocketFlag_OnExplodeCmd = 1 << 9,
  96. RocketFlag_CustomModel = 1 << 10,
  97. RocketFlag_CustomSpawnSound = 1 << 11,
  98. RocketFlag_CustomBeepSound = 1 << 12,
  99. RocketFlag_CustomAlertSound = 1 << 13,
  100. RocketFlag_Elevating = 1 << 14,
  101. RocketFlag_IsAnimated = 1 << 15
  102. };
  103.  
  104. enum RocketSound
  105. {
  106. RocketSound_Spawn,
  107. RocketSound_Beep,
  108. RocketSound_Alert
  109. };
  110.  
  111. enum SpawnerFlags
  112. {
  113. SpawnerFlag_Team_Red = 1,
  114. SpawnerFlag_Team_Blu = 2,
  115. SpawnerFlag_Team_Both = 3
  116. };
  117.  
  118. #define TestFlags(%1,%2) (!!((%1) & (%2)))
  119. #define TestFlagsAnd(%1,%2) (((%1) & (%2)) == %2)
  120.  
  121. // ---- Other resources ------------------------------------------------------------
  122. #define SOUND_DEFAULT_SPAWN "weapons/sentry_rocket.wav"
  123. #define SOUND_DEFAULT_BEEP "weapons/sentry_scan.wav"
  124. #define SOUND_DEFAULT_ALERT "weapons/sentry_spot.wav"
  125. #define SOUND_DEFAULT_SPEEDUPALERT "misc/doomsday_lift_warning.wav"
  126. #define SNDCHAN_MUSIC 32
  127. #define PARTICLE_NUKE_1 "fireSmokeExplosion"
  128. #define PARTICLE_NUKE_2 "fireSmokeExplosion1"
  129. #define PARTICLE_NUKE_3 "fireSmokeExplosion2"
  130. #define PARTICLE_NUKE_4 "fireSmokeExplosion3"
  131. #define PARTICLE_NUKE_5 "fireSmokeExplosion4"
  132. #define PARTICLE_NUKE_COLLUMN "fireSmoke_collumnP"
  133. #define PARTICLE_NUKE_1_ANGLES view_as<float> ({270.0, 0.0, 0.0})
  134. #define PARTICLE_NUKE_2_ANGLES PARTICLE_NUKE_1_ANGLES
  135. #define PARTICLE_NUKE_3_ANGLES PARTICLE_NUKE_1_ANGLES
  136. #define PARTICLE_NUKE_4_ANGLES PARTICLE_NUKE_1_ANGLES
  137. #define PARTICLE_NUKE_5_ANGLES PARTICLE_NUKE_1_ANGLES
  138. #define PARTICLE_NUKE_COLLUMN_ANGLES PARTICLE_NUKE_1_ANGLES
  139.  
  140. #define MAXMULTICOLORHUD 5
  141.  
  142. // Debug
  143. //#define DEBUG
  144.  
  145. // *********************************************************************************
  146. // VARIABLES
  147. // *********************************************************************************
  148.  
  149. // -----<<< Cvars >>>-----
  150. Handle g_hCvarEnabled;
  151. Handle g_hCvarEnableCfgFile;
  152. Handle g_hCvarDisableCfgFile;
  153. Handle g_hCvarSpeedo;
  154. Handle g_hCvarAnnounce;
  155. Handle g_hCvarPyroVisionEnabled = INVALID_HANDLE;
  156. Handle g_hCvarAirBlastCommandEnabled;
  157. Handle g_hCvarDeflectCountAnnounce;
  158. Handle g_hCvarRedirectBeep;
  159. Handle g_hCvarPreventTauntKillEnabled;
  160. Handle g_hCvarStealPrevention;
  161. Handle g_hCvarStealPreventionNumber;
  162.  
  163. Handle g_hCvarDelayPrevention;
  164. Handle g_hCvarDelayPreventionTime;
  165. Handle g_hCvarDelayPreventionSpeedup;
  166. Handle g_hCvarVoteRocketClassCommandEnabled;
  167. Handle g_hCvarVoteClassPercentage;
  168. Handle g_hCvarVoteClassCooldown;
  169. Handle g_hCvarServerChatTag;
  170. Handle g_hCvarMainChatColor;
  171. Handle g_hCvarKeywordChatColor;
  172. Handle g_hCvarClientChatColor;
  173. Handle g_hCvarNameHud;
  174.  
  175.  
  176. ConVar g_hTouchAnnounce;
  177.  
  178. // -----<<< Gameplay >>>-----
  179. bool IsOnTouch;
  180. bool IsOnGameFrame;
  181. //int g_stolen[MAXPLAYERS + 1];
  182. bool g_bEnabled; // Is the plugin enabled?
  183. bool g_bRoundStarted; // Has the round started?
  184. int g_iRoundCount; // Current round count since map start
  185. int g_iRocketsFired; // No. of rockets fired since round start
  186. //Handle g_hLogicTimer; // Logic timer
  187. float g_fLastSpawnTime; // Time at which the last rocket had spawned
  188. float g_fNextSpawnTime; // Time at which the next rocket will be able to spawn
  189. int g_iLastDeadTeam; // The team of the last dead client. If none, it's a random team.
  190. int g_iLastDeadClient; // The last dead client. If none, it's a random client.
  191. int g_iPlayerCount;
  192. int gDeflector;
  193. Handle g_hHud;
  194. Handle g_h1v1Hud;
  195. Handle g_hNameHud;
  196. int g_iRocketSpeed;
  197. int g_hRocketSpeed;
  198. int xDeflections;
  199. Handle g_hTimerHud;
  200.  
  201. enum eRocketSteal
  202. {
  203. stoleRocket = false,
  204. rocketsStolen
  205. };
  206.  
  207. int bStealArray[MAXPLAYERS + 1][eRocketSteal];
  208.  
  209. // -----<<< Configuration >>>-----
  210. bool g_bMusicEnabled;
  211. bool g_bMusic[view_as<int>(SizeOfMusicsArray)];
  212. char g_strMusic[view_as<int>(SizeOfMusicsArray)][PLATFORM_MAX_PATH];
  213. bool g_bUseWebPlayer;
  214. char g_strWebPlayerUrl[256];
  215.  
  216. char g_strServerChatTag[256];
  217. char g_strMainChatColor[256];
  218. char g_strKeywordChatColor[256];
  219. char g_strClientChatColor[256];
  220. char g_strNameHud[256];
  221. // -----<<< Structures >>>-----
  222. // Rockets
  223. bool g_bRocketIsValid[MAX_ROCKETS];
  224. bool g_bRocketIsNuke[MAX_ROCKETS];
  225. bool g_bPreventingDelay;
  226. int g_iRocketEntity[MAX_ROCKETS];
  227. int g_iRocketTarget[MAX_ROCKETS];
  228. int g_iRocketSpawner[MAX_ROCKETS];
  229. int g_iRocketClass[MAX_ROCKETS];
  230. RocketFlags g_iRocketFlags[MAX_ROCKETS];
  231. float g_fRocketSpeed[MAX_ROCKETS];
  232. float g_fRocketDirection[MAX_ROCKETS][3];
  233. int g_iRocketDeflections[MAX_ROCKETS];
  234. float g_fRocketLastDeflectionTime[MAX_ROCKETS];
  235. float g_fRocketLastBeepTime[MAX_ROCKETS];
  236. int g_iLastCreatedRocket;
  237. int g_iRocketCount;
  238. float g_fSavedSpeed;
  239. float g_fSavedSpeedIncrement;
  240.  
  241. // Classes
  242. char g_strRocketClassName[MAX_ROCKET_CLASSES][16];
  243. char g_strRocketClassLongName[MAX_ROCKET_CLASSES][32];
  244. char g_strSavedClassName[32];
  245. BehaviourTypes g_iRocketClassBehaviour[MAX_ROCKET_CLASSES];
  246. char g_strRocketClassModel[MAX_ROCKET_CLASSES][PLATFORM_MAX_PATH];
  247. RocketFlags g_iRocketClassFlags[MAX_ROCKET_CLASSES];
  248. float g_fRocketClassBeepInterval[MAX_ROCKET_CLASSES];
  249. char g_strRocketClassSpawnSound[MAX_ROCKET_CLASSES][PLATFORM_MAX_PATH];
  250. char g_strRocketClassBeepSound[MAX_ROCKET_CLASSES][PLATFORM_MAX_PATH];
  251. char g_strRocketClassAlertSound[MAX_ROCKET_CLASSES][PLATFORM_MAX_PATH];
  252. float g_fRocketClassCritChance[MAX_ROCKET_CLASSES];
  253. float g_fRocketClassDamage[MAX_ROCKET_CLASSES];
  254. float g_fRocketClassDamageIncrement[MAX_ROCKET_CLASSES];
  255. float g_fRocketClassSpeed[MAX_ROCKET_CLASSES];
  256. float g_fRocketClassSpeedIncrement[MAX_ROCKET_CLASSES];
  257. float g_fRocketClassTurnRate[MAX_ROCKET_CLASSES];
  258. float g_fRocketClassTurnRateIncrement[MAX_ROCKET_CLASSES];
  259. float g_fRocketClassElevationRate[MAX_ROCKET_CLASSES];
  260. float g_fRocketClassElevationLimit[MAX_ROCKET_CLASSES];
  261. float g_fRocketClassRocketsModifier[MAX_ROCKET_CLASSES];
  262. float g_fRocketClassPlayerModifier[MAX_ROCKET_CLASSES];
  263. float g_fRocketClassControlDelay[MAX_ROCKET_CLASSES];
  264. float g_fRocketClassTargetWeight[MAX_ROCKET_CLASSES];
  265. Handle g_hRocketClassCmdsOnSpawn[MAX_ROCKET_CLASSES];
  266. Handle g_hRocketClassCmdsOnDeflect[MAX_ROCKET_CLASSES];
  267. Handle g_hRocketClassCmdsOnKill[MAX_ROCKET_CLASSES];
  268. Handle g_hRocketClassCmdsOnExplode[MAX_ROCKET_CLASSES];
  269. Handle g_hRocketClassTrie;
  270. char g_iRocketClassCount;
  271.  
  272. // Spawner classes
  273. char g_strSpawnersName[MAX_SPAWNER_CLASSES][32];
  274. int g_iSpawnersMaxRockets[MAX_SPAWNER_CLASSES];
  275. float g_fSpawnersInterval[MAX_SPAWNER_CLASSES];
  276. Handle g_hSpawnersChancesTable[MAX_SPAWNER_CLASSES];
  277. Handle g_hSpawnersTrie;
  278. int g_iSpawnersCount;
  279.  
  280. // Array containing the spawn points for the Red team, and
  281. // their associated spawner class.
  282. int g_iCurrentRedSpawn;
  283. int g_iSpawnPointsRedCount;
  284. int g_iSpawnPointsRedClass[MAX_SPAWN_POINTS];
  285. int g_iSpawnPointsRedEntity[MAX_SPAWN_POINTS];
  286.  
  287. // Array containing the spawn points for the Blu team, and
  288. // their associated spawner class.
  289. int g_iCurrentBluSpawn;
  290. int g_iSpawnPointsBluCount;
  291. int g_iSpawnPointsBluClass[MAX_SPAWN_POINTS];
  292. int g_iSpawnPointsBluEntity[MAX_SPAWN_POINTS];
  293.  
  294. // The default spawner class.
  295. int g_iDefaultRedSpawner;
  296. int g_iDefaultBluSpawner;
  297.  
  298. //Observer
  299. int g_observer;
  300. int g_op_rocket;
  301.  
  302. //Voting
  303.  
  304. bool g_bVoteClassEnabled; // check if players are allowed to vote for a rocket class change
  305. bool g_bCanVoteClass; // check if voting for rocket class is on cooldown
  306. bool g_bClassVoted[MAXPLAYERS + 1] = {false, ...}; // check which players have voted for a rocket class change
  307. int g_iClassVoters = 0; // maximum number of votes
  308. int g_iClassVotes = 0; // how many rocket class votes recieved
  309. int g_iClassVotesRequired; // how many rocket class votes are needed
  310. int g_iTimeVoted = 0;
  311. int iVotes;
  312. bool iVote[MAXPLAYERS + 1] = false;
  313. Handle g_percentVote = null;
  314. bool bounceActivated = true;
  315. bool godmode = false;
  316. ConVar cV_enabled;
  317.  
  318. // *********************************************************************************
  319. // PLUGIN
  320. // *********************************************************************************
  321. public Plugin myinfo =
  322. {
  323. name = PLUGIN_NAME,
  324. author = PLUGIN_AUTHOR,
  325. description = PLUGIN_NAME,
  326. version = PLUGIN_VERSION,
  327. url = PLUGIN_CONTACT
  328. };
  329.  
  330. // *********************************************************************************
  331. // METHODS
  332. // *********************************************************************************
  333.  
  334. /* OnPluginStart()
  335. **
  336. ** When the plugin is loaded.
  337. ** -------------------------------------------------------------------------- */
  338. public void OnPluginStart()
  339. {
  340. char strModName[32]; GetGameFolderName(strModName, sizeof(strModName));
  341. if (!StrEqual(strModName, "tf"))SetFailState("This plugin is only for Team Fortress 2.");
  342.  
  343. CreateConVar("tf_dodgeballupdated_version", PLUGIN_VERSION, PLUGIN_NAME, FCVAR_SPONLY | FCVAR_UNLOGGED | FCVAR_DONTRECORD | FCVAR_REPLICATED | FCVAR_NOTIFY);
  344. g_percentVote = CreateConVar("sm_percentageVotes", "50.0", "Needed percentage to activate the superbot", _, true, 0.0, true, 100.0);
  345. g_hCvarEnabled = CreateConVar("tf_dodgeball_enabled", "1", "Enable Dodgeball on TFDB maps?", _, true, 0.0, true, 1.0);
  346. g_hCvarEnableCfgFile = CreateConVar("tf_dodgeball_enablecfg", "sourcemod/dodgeball_enable.cfg", "Config file to execute when enabling the Dodgeball game mode.", FCVAR_PROTECTED);
  347. g_hCvarDisableCfgFile = CreateConVar("tf_dodgeball_disablecfg", "sourcemod/dodgeball_disable.cfg", "Config file to execute when disabling the Dodgeball game mode.", FCVAR_PROTECTED);
  348. g_hCvarSpeedo = CreateConVar("tf_dodgeball_speedo", "1", "Enable HUD speedometer", FCVAR_PROTECTED);
  349. g_hCvarAnnounce = CreateConVar("tf_dodgeball_announce", "1", "Enable kill announces in chat", FCVAR_PROTECTED);
  350. g_hCvarPyroVisionEnabled = CreateConVar("tf_dodgeball_pyrovision", "0", "Enable pyrovision for everyone", FCVAR_PROTECTED);
  351. g_hMaxBouncesConVar = CreateConVar("tf_dodgeball_rbmax", "10000", "Max number of times a rocket will bounce.", FCVAR_PROTECTED, true, 0.0, false);
  352. g_hCvarAirBlastCommandEnabled = CreateConVar("tf_dodgeball_airblast", "1", "Enable if airblast is enabled or not", FCVAR_PROTECTED);
  353. g_hCvarDeflectCountAnnounce = CreateConVar("tf_dodgeball_count_deflect", "1", "Enable number of deflections in kill announce", FCVAR_PROTECTED);
  354. g_hCvarRedirectBeep = CreateConVar("tf_dodgeball_rdrbeep", "1", "Do redirects beep?", FCVAR_PROTECTED);
  355. g_hCvarPreventTauntKillEnabled = CreateConVar("tf_dodgeball_block_tauntkill", "0", "Block taunt kills?", FCVAR_PROTECTED);
  356. g_hCvarStealPrevention = CreateConVar("tf_dodgeball_steal_prevention", "0", "Enable steal prevention?", FCVAR_PROTECTED);
  357. g_hCvarStealPreventionNumber = CreateConVar("tf_dodgeball_sp_number", "3", "How many steals before you get slayed?", FCVAR_PROTECTED);
  358.  
  359. g_hCvarDelayPrevention = CreateConVar("tf_dodgeball_delay_prevention", "0", "Enable delay prevention?", FCVAR_PROTECTED);
  360. g_hCvarDelayPreventionTime = CreateConVar("tf_dodgeball_dp_time", "5", "How much time (in seconds) before delay prevention activates?", FCVAR_PROTECTED, true, 0.0, false);
  361. g_hCvarDelayPreventionSpeedup = CreateConVar("tf_dodgeball_dp_speedup", "100", "How much speed (in hammer units per second) should the rocket gain (20 Refresh Rate for every 0.1 seconds) for delay prevention? Multiply by (15/352) for mph.", FCVAR_NONE, true, 0.0, false);
  362. g_hCvarVoteRocketClassCommandEnabled = CreateConVar("tf_dodgeball_voteclass", "1", "Should voting for rocket class be enabled or not?", FCVAR_PROTECTED);
  363. g_hCvarVoteClassPercentage = CreateConVar("tf_dodgeball_voteclass_percentage", "0.60", "Percentage of votes required to change rocket class.", FCVAR_PROTECTED, true, 0.0, true, 1.0);
  364. g_hCvarVoteClassCooldown = CreateConVar("tf_dodgeball_voteclass_cooldown", "30", "Seconds before another vote for rocket class can be initated.", FCVAR_PROTECTED, true, 0.0);
  365.  
  366. g_hCvarServerChatTag = CreateConVar("tf_dodgeball_servertag", "{DARKOLIVEGREEN}[TFDB]", "Tag that appears at the start of each chat announcement.", FCVAR_PROTECTED);
  367. g_hCvarMainChatColor = CreateConVar("tf_dodgeball_maincolor", "{WHITE}", "Color assigned to the majority of the words in chat announcements.");
  368. g_hCvarKeywordChatColor = CreateConVar("tf_dodgeball_keywordcolor", "{DARKOLIVEGREEN}", "Color assigned to the most important words in chat announcements.", FCVAR_PROTECTED);
  369. g_hCvarClientChatColor = CreateConVar("tf_dodgeball_clientwordcolor", "{ORANGE}", "Color assigned to the client in chat announcements.", FCVAR_PROTECTED);
  370. g_hCvarNameHud = CreateConVar("tf_dodgeball_serverhud", "Extale Studio", "This is the server's name'", FCVAR_PROTECTED);
  371.  
  372.  
  373. g_hTouchAnnounce = CreateConVar("tf_dodgeball_touchannounce", "1", "Announce speeds on touch instead of on death.", FCVAR_NONE, true, 0.0, true, 1.0);
  374.  
  375. // Commands
  376. RegConsoleCmd("sm_ab", Command_ToggleAirblast, USAGE);
  377. RegAdminCmd("sm_tfdb", Command_DodgeballAdminMenu, ADMFLAG_GENERIC, "A menu for admins to modify things inside the plugin.");
  378.  
  379. RegConsoleCmd("sm_currentrocket", Command_PostCurrentRocketClass, "Posts a chat message of the name of the current main rocket class.");
  380. RegConsoleCmd("sm_voterocket", Command_VoteRocketClass, "Vote to change the current rocket class.");
  381. RegAdminCmd("sm_class", Command_SetRocketClass, ADMFLAG_GENERIC, "Set the main rocket class via name.");
  382. RegAdminCmd("sm_reload", Command_Reload, ADMFLAG_GENERIC, "sm_reload - Reload Dodgeball yesyes.");
  383. RegAdminCmd("sm_unload", Command_Unload, ADMFLAG_GENERIC, "sm_unload - unload Dodgeball yesyes.");
  384. RegAdminCmd("sm_load", Command_Load, ADMFLAG_GENERIC, "sm_load - load Dodgeball yesyes.");
  385. RegConsoleCmd("sm_votebounce", Command_VotePVB, "Vote for the bounce");
  386.  
  387. ServerCommand("tf_arena_use_queue 0");
  388.  
  389. HookConVarChange(g_hMaxBouncesConVar, tf2dodgeball_hooks);
  390. HookConVarChange(g_hCvarPyroVisionEnabled, tf2dodgeball_hooks);
  391.  
  392. HookConVarChange(g_hCvarVoteRocketClassCommandEnabled, tf2dodgeball_hooks);
  393. HookConVarChange(g_hCvarVoteClassPercentage, tf2dodgeball_hooks);
  394. HookConVarChange(g_hCvarVoteClassCooldown, tf2dodgeball_hooks);
  395.  
  396. g_bVoteClassEnabled = GetConVarBool(g_hCvarVoteRocketClassCommandEnabled);
  397.  
  398.  
  399. HookConVarChange(g_hCvarServerChatTag, tf2dodgeball_hooks);
  400. HookConVarChange(g_hCvarMainChatColor, tf2dodgeball_hooks);
  401. HookConVarChange(g_hCvarKeywordChatColor, tf2dodgeball_hooks);
  402. HookConVarChange(g_hCvarClientChatColor, tf2dodgeball_hooks);
  403.  
  404. GetConVarString(g_hCvarServerChatTag, g_strServerChatTag, sizeof(g_strServerChatTag));
  405. GetConVarString(g_hCvarMainChatColor, g_strMainChatColor, sizeof(g_strMainChatColor));
  406. GetConVarString(g_hCvarKeywordChatColor, g_strKeywordChatColor, sizeof(g_strKeywordChatColor));
  407. GetConVarString(g_hCvarClientChatColor, g_strClientChatColor, sizeof(g_strClientChatColor));
  408. GetConVarString(g_hCvarNameHud, g_strNameHud, sizeof(g_strNameHud));
  409.  
  410. cV_enabled = FindConVar("sm_ovo_enabled");
  411. cV_enabled = CreateConVar("sm_ovo_enabled", "1.0", "Enabled or disabled", _, true, 0.0, true, 1.0);
  412. if(cV_enabled != null) {
  413. HookConVarChange(cV_enabled, CVarChanged);
  414. }
  415.  
  416. g_hRocketClassTrie = CreateTrie();
  417. g_hSpawnersTrie = CreateTrie();
  418.  
  419. g_bCanVoteClass = true;
  420.  
  421. g_hHud = CreateHudSynchronizer();
  422. g_h1v1Hud = CreateHudSynchronizer();
  423. g_hNameHud = CreateHudSynchronizer();
  424.  
  425.  
  426. LoadTranslations("tf2dodgeball.phrases");
  427. AutoExecConfig(true, "tf2_dodgeball");
  428.  
  429. RegisterCommands();
  430.  
  431. for (int i = 1; i <= MaxClients; i++)
  432. {
  433. if (IsClientInGame(i))
  434. {
  435. SDKHook(i, SDKHook_OnTakeDamage, OnTakeDamage);
  436. }
  437. }
  438. SetGodmodeState();
  439. }
  440.  
  441.  
  442.  
  443.  
  444. bool PluginDisabled() {
  445. return !GetConVarBool(cV_enabled);
  446. }
  447.  
  448. public void CVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) {
  449. cV_enabled = FindConVar("sm_ovo_enabled");
  450. }
  451. public bool SetGodmodeState()
  452. {
  453. if(PluginDisabled()) {
  454. return false;
  455. }
  456.  
  457. int playerCount = GetTeamClientCount(3) + GetTeamClientCount(2);
  458. if (playerCount == 2)
  459. {
  460. if (godmode != true)
  461. {
  462. CPrintToChatAll("{DARKOLIVEGREEN}[{DEFAULT}TFDB{DARKOLIVEGREEN}] {DEFAULT}2 players found, {TURQUOISE}Enabling {DEFAULT}1{ORANGE}v{DEFAULT}1 Mode");
  463. }
  464. godmode = true;
  465. }
  466. else
  467. {
  468. if (godmode)
  469. {
  470. CPrintToChatAll("{DARKOLIVEGREEN}[{DEFAULT}TFDB{DARKOLIVEGREEN}] {DEFAULT}More than 2 players found, Disabling {DEFAULT}1{ORANGE}v{DEFAULT}1 Mode");
  471. }
  472. godmode = false;
  473. }
  474. return godmode;
  475. }
  476.  
  477. public void OnRoundActive(Handle event, char[] name, bool dontBroadcast)
  478. {
  479. SetGodmodeState();
  480. CreateTimer(1.0, Truc);
  481. }
  482.  
  483. public void OnTeamSwitch(Event event, char[] name, bool dontBroadcast)
  484. {
  485. SetGodmodeState();
  486. }
  487.  
  488. public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom)
  489. {
  490. if(PluginDisabled()) {
  491. return Plugin_Continue;
  492. }
  493.  
  494. SetGodmodeState();
  495. if (godmode)
  496. {
  497. damage = 0.0;
  498. return Plugin_Changed;
  499. }
  500. return Plugin_Continue;
  501. }
  502.  
  503.  
  504.  
  505. /*
  506. ** ▄▀ ▄▀▄ █░█ █▄░█ ▀█▀
  507. ** █░ █░█ █░█ █░▀█ ░█░
  508. ** ░▀ ░▀░ ░▀░ ▀░░▀ ░▀░
  509. ***********************************/
  510. stock int GetAllClientCount() {
  511. int count = 0;
  512. for (int i = 1; i <= MaxClients; i++) {
  513. if (IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) > 1) {
  514. count += 1;
  515. }
  516. }
  517. return count;
  518. }
  519.  
  520. ///////////////////////
  521.  
  522. public Action Command_VotePVB(int client, int args) {
  523. int iNeededVotes = RoundToCeil((GetAllClientCount() * GetConVarFloat(g_percentVote)) / 100.0);
  524. if (!iVote[client] && IsValidClient(client))
  525. {
  526. iVotes++;
  527. if (!bounceActivated)
  528. {
  529. CPrintToChatAll("%s %s%N %swants to enable Rocket Bounce! (%s%i%s/%s%i%s).", g_strServerChatTag, g_strClientChatColor, client, g_strMainChatColor, g_strKeywordChatColor, iVotes, g_strMainChatColor, g_strKeywordChatColor, iNeededVotes, g_strMainChatColor);
  530. }
  531. else
  532. {
  533. CPrintToChatAll("%s %s%N %swants to disable Rocket Bounce! (%s%i%s/%s%i%s).", g_strServerChatTag, g_strClientChatColor, client, g_strMainChatColor, g_strKeywordChatColor, iVotes, g_strMainChatColor, g_strKeywordChatColor, iNeededVotes, g_strMainChatColor);
  534. }
  535. iVote[client] = true;
  536. } else if (iVote[client] && IsValidClient(client)) {
  537. CPrintToChat(client, "%s %s%N %syou can't vote twice!", g_strServerChatTag, g_strClientChatColor, client, g_strMainChatColor);
  538. }
  539. if (iVotes >= iNeededVotes) {
  540. if (!bounceActivated) {
  541. CPrintToChatAll("%s %sRocket Bounce is now %sactivated%s!", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor, g_strMainChatColor);
  542. EnableMode();
  543. }
  544. else {
  545. CPrintToChatAll("%s %sRocket Bounce is now %sdisabled%s!", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor, g_strMainChatColor);
  546. DisableMode();
  547. }
  548. iVote[client] = false;
  549. iVotes = 0;
  550. }
  551. return Plugin_Handled;
  552. }
  553.  
  554. /*
  555. **█▀▀ █▄░█ ▄▀▄ █▀▄ █░░ █▀▀ ▄▀▄ █▀▀▄ █▀▄ ▀ ▄▀▀ ▄▀▄ █▀▄ █░░ █▀▀
  556. **█▀▀ █░▀█ █▀█ █▀█ █░▄ █▀▀ █░█ █▐█▀ █░█ █ ░▀▄ █▀█ █▀█ █░▄ █▀▀
  557. **▀▀▀ ▀░░▀ ▀░▀ ▀▀░ ▀▀▀ ▀▀▀ ░▀░ ▀░▀▀ ▀▀░ ▀ ▀▀░ ▀░▀ ▀▀░ ▀▀▀ ▀▀▀
  558. ***********************************************************************************/
  559.  
  560. stock void EnableMode()
  561. {
  562. EnableBounce();
  563. bounceActivated = true;
  564. }
  565.  
  566. stock void EnableBounce()
  567. {
  568. ServerCommand("sm_cvar tf_dodgeball_rbmax 999");
  569. }
  570.  
  571. stock void DisableMode()
  572. {
  573. DisableBounce();
  574. bounceActivated = false;
  575. }
  576.  
  577. stock void DisableBounce()
  578. {
  579. ServerCommand("sm_cvar tf_dodgeball_rbmax 0");
  580. }
  581.  
  582. public Action Command_Reload(int client, int args)
  583. {
  584. ServerCommand("sm plugins reload Dodgeballtouch");
  585. CPrintToChatAll("%s %sPlugin has been %sreloaded%s.", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor, g_strMainChatColor);
  586. }
  587.  
  588. public Action Command_Unload(int client, int args)
  589. {
  590. ServerCommand("sm plugins unload Dodgeballtouch");
  591. CPrintToChatAll("%s %sPlugin has been %sunloaded%s.", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor, g_strMainChatColor);
  592. }
  593.  
  594. public Action Command_Load(int client, int args)
  595. {
  596. ServerCommand("sm plugins load Dodgeballtouch");
  597. CPrintToChatAll("%s %sPlugin has been %sloaded%s.", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor, g_strMainChatColor);
  598. }
  599.  
  600. /* OnConfigsExecuted()
  601. **
  602. ** When all the configuration files have been executed, try to enable the
  603. ** Dodgeball.
  604. ** -------------------------------------------------------------------------- */
  605. public void OnConfigsExecuted()
  606. {
  607. if (GetConVarBool(g_hCvarEnabled) && IsDodgeBallMap())
  608. {
  609. EnableDodgeBall();
  610. }
  611. }
  612.  
  613. /* OnMapStart()
  614. **
  615. ** When the map starts, clear vote variables.
  616. ** -------------------------------------------------------------------------- */
  617.  
  618. public void OnMapStart()
  619. {
  620. g_iClassVoters = 0;
  621. g_iClassVotes = 0;
  622. g_iClassVotesRequired = 0;
  623. }
  624.  
  625. /* OnMapEnd()
  626. **
  627. ** When the map ends, disable DodgeBall.
  628. ** -------------------------------------------------------------------------- */
  629. public void OnMapEnd()
  630. {
  631. DisableDodgeBall();
  632.  
  633. g_bVoteClassEnabled = false;
  634. }
  635.  
  636. public Action Command_SetRocketClass(int client, int args)
  637. {
  638. if (args < 1)
  639. {
  640. ReplyToCommand(client, "[SM] Usage: sm_class <rocketclassname>");
  641. return Plugin_Handled;
  642. }
  643.  
  644. char class[PLATFORM_MAX_PATH];
  645. GetCmdArg(1, class, sizeof(class));
  646.  
  647. int classIndex = FindRocketClass(class);
  648.  
  649. if (classIndex == -1)
  650. {
  651. ReplyToCommand(client, "%t", "Rocket class was not found", class);
  652. return Plugin_Handled;
  653. }
  654.  
  655. ShowActivity2(client, "", "%t", "Changed rocket class", class);
  656. LogAction(client, -1, "\"%L\" changed rocket class to \"%s\"", client, class);
  657.  
  658. SetMainRocketClass(classIndex, false);
  659.  
  660. return Plugin_Handled;
  661. }
  662.  
  663. public Action Command_DodgeballAdminMenu(int client, int args)
  664. {
  665. Menu menu = new Menu(DodgeballAdmin_Handler, MENU_ACTIONS_ALL);
  666.  
  667. menu.SetTitle("Dodgeball Admin Menu");
  668.  
  669. menu.AddItem("0", "Max Rocket Count");
  670. menu.AddItem("1", "Speed Multiplier");
  671. menu.AddItem("2", "Main Rocket Class");
  672. menu.AddItem("3", "Refresh Configurations");
  673. menu.AddItem("4", "Reload Plugin");
  674. menu.AddItem("5", "Enable Rocket Bounce");
  675. menu.ExitButton = true;
  676. menu.Display(client, MENU_TIME_FOREVER);
  677.  
  678. return Plugin_Handled;
  679. }
  680.  
  681. public int DodgeballAdmin_Handler(Menu menu, MenuAction action, int param1, int param2)
  682. {
  683. switch (action)
  684. {
  685. case MenuAction_Start:
  686. {
  687. // It's important to log anything in any way, the best is printtoserver, but if you just want to log to client to make it easier to get progress done, feel free.
  688. PrintToServer("Displaying menu"); // Log it
  689. }
  690.  
  691. case MenuAction_Display:
  692. {
  693. PrintToServer("Client %d was sent menu with panel %x", param1, param2); // Log so you can check if it gets sent.
  694. }
  695.  
  696. case MenuAction_Select:
  697. {
  698. char sInfo[32];
  699. menu.GetItem(param2, sInfo, sizeof(sInfo));
  700.  
  701. switch (param2)
  702. {
  703. case 0:
  704. {
  705. DrawMaxRocketCountMenu(param1);
  706. }
  707. case 1:
  708. {
  709. DrawRocketSpeedMenu(param1);
  710. }
  711. case 2:
  712. {
  713. if (!g_strSavedClassName[0]) {
  714. CPrintToChat(param1, "%s %sNo main rocket class detected, %saborting%s...", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor, g_strMainChatColor);
  715. return;
  716. }
  717. DrawRocketClassMenu(param1);
  718. }
  719. case 3:
  720. {
  721. // Clean up everything
  722. DestroyRocketClasses();
  723. DestroySpawners();
  724. // Then reinitialize
  725. char strMapName[64]; GetCurrentMap(strMapName, sizeof(strMapName));
  726. char strMapFile[PLATFORM_MAX_PATH]; Format(strMapFile, sizeof(strMapFile), "%s.cfg", strMapName);
  727. ParseConfigurations();
  728. ParseConfigurations(strMapFile);
  729. CPrintToChatAll("%s %s%N %srefreshed the %sdodgeball configs%s.", g_strServerChatTag, g_strClientChatColor, param1, g_strMainChatColor, g_strKeywordChatColor, g_strMainChatColor);
  730. }
  731. case 4:
  732. {
  733. ServerCommand("sm plugins reload Dodgeballtouch");
  734. CPrintToChatAll("%s %sPlugin has been %sreloaded%s.", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor, g_strMainChatColor);
  735. }
  736. case 5:
  737. {
  738. DrawRocketBounceMenu(param1);
  739. }
  740. }
  741. }
  742.  
  743. case MenuAction_Cancel:
  744. {
  745. PrintToServer("Client %d's menu was cancelled for reason %d", param1, param2); // Logging once again.
  746. }
  747.  
  748. case MenuAction_End:
  749. {
  750. delete menu;
  751. }
  752.  
  753. case MenuAction_DrawItem:
  754. {
  755. int style;
  756. char info[32];
  757. menu.GetItem(param2, info, sizeof(info), style);
  758. }
  759.  
  760. case MenuAction_DisplayItem:
  761. {
  762. char info[32];
  763. menu.GetItem(param2, info, sizeof(info));
  764. }
  765. }
  766. }
  767.  
  768. void DrawRocketBounceMenu(int client)
  769. {
  770. Menu menu = new Menu(DodgeballRocketBounce_Handler, MENU_ACTIONS_ALL);
  771.  
  772. menu.SetTitle("Enable / Disable Bounce?");
  773.  
  774. menu.AddItem("1", "Enable");
  775. menu.AddItem("2", "Disable");
  776.  
  777. menu.ExitButton = true;
  778. menu.Display(client, MENU_TIME_FOREVER);
  779. }
  780.  
  781. void DrawMaxRocketCountMenu(int client)
  782. {
  783. Menu menu = new Menu(DodgeballAdminRocketCount_Handler, MENU_ACTIONS_ALL);
  784.  
  785. menu.SetTitle("How many rockets?");
  786.  
  787. menu.AddItem("1", "One");
  788. menu.AddItem("2", "Two");
  789. menu.AddItem("3", "Three");
  790. menu.AddItem("4", "Four");
  791. menu.AddItem("5", "Five");
  792.  
  793. menu.ExitButton = true;
  794. menu.Display(client, MENU_TIME_FOREVER);
  795. }
  796.  
  797. void DrawRocketSpeedMenu(int client)
  798. {
  799. Menu menu = new Menu(DodgeballAdminRocketSpeed_Handler, MENU_ACTIONS_ALL);
  800.  
  801. menu.SetTitle("How fast should the rockets go?");
  802.  
  803. menu.AddItem("1", "25% (Slow)");
  804. menu.AddItem("2", "50% (Normal)");
  805. menu.AddItem("3", "75% (Fast)");
  806. menu.AddItem("4", "100% (Silly Fast)");
  807.  
  808. menu.ExitButton = true;
  809. menu.Display(client, MENU_TIME_FOREVER);
  810. }
  811.  
  812. void DrawRocketClassMenu(int client)
  813. {
  814. Menu menu = new Menu(DodgeballAdminRocketClass_Handler, MENU_ACTIONS_ALL);
  815.  
  816. menu.SetTitle("Which class should the rocket be set to?");
  817.  
  818. for (int currentClass = 0; currentClass < g_iRocketClassCount; currentClass++)
  819. {
  820. char classNumber[16];
  821. IntToString(currentClass, classNumber, sizeof(classNumber));
  822. if (StrEqual(g_strSavedClassName, g_strRocketClassLongName[currentClass]))
  823. {
  824. char currentClassName[32];
  825. strcopy(currentClassName, sizeof(currentClassName), "[Current] ");
  826. StrCat(currentClassName, sizeof(currentClassName), g_strSavedClassName);
  827. menu.AddItem(classNumber, currentClassName);
  828. }
  829. else menu.AddItem(classNumber, g_strRocketClassLongName[currentClass]);
  830. }
  831.  
  832. menu.ExitButton = true;
  833. menu.Display(client, MENU_TIME_FOREVER);
  834. }
  835.  
  836. public int DodgeballRocketBounce_Handler(Menu menu, MenuAction action, int param1, int param2)
  837. {
  838. switch (action)
  839. {
  840. case MenuAction_Start:
  841. {
  842. // It's important to log anything in any way, the best is printtoserver, but if you just want to log to client to make it easier to get progress done, feel free.
  843. PrintToServer("Displaying menu"); // Log it
  844. }
  845.  
  846. case MenuAction_Display:
  847. {
  848. PrintToServer("Client %d was sent menu with panel %x", param1, param2); // Log so you can check if it gets sent.
  849. }
  850.  
  851. case MenuAction_Select:
  852. {
  853. char sInfo[32];
  854. menu.GetItem(param2, sInfo, sizeof(sInfo));
  855.  
  856. switch (param2)
  857. {
  858. case 0:
  859. {
  860. ServerCommand("sm_cvar tf_dodgeball_rbmax 999");
  861. CPrintToChatAll("%s %s%N %sEnabled Rocket %sBounce.", g_strServerChatTag, g_strClientChatColor, param1, g_strMainChatColor, g_strKeywordChatColor);
  862. }
  863. case 1:
  864. {
  865. ServerCommand("sm_cvar tf_dodgeball_rbmax 0");
  866. CPrintToChatAll("%s %s%N %sDisabled Rocket %sBounce.", g_strServerChatTag, g_strClientChatColor, param1, g_strMainChatColor, g_strKeywordChatColor);
  867. }
  868. }
  869. }
  870. case MenuAction_Cancel:
  871. {
  872. PrintToServer("Client %d's menu was cancelled for reason %d", param1, param2); // Logging once again.
  873. }
  874.  
  875. case MenuAction_End:
  876. {
  877. delete menu;
  878. }
  879.  
  880. case MenuAction_DrawItem:
  881. {
  882. int style;
  883. char info[32];
  884. menu.GetItem(param2, info, sizeof(info), style);
  885. }
  886.  
  887. case MenuAction_DisplayItem:
  888. {
  889. char info[32];
  890. menu.GetItem(param2, info, sizeof(info));
  891. }
  892. }
  893. }
  894.  
  895. public int DodgeballAdminRocketCount_Handler(Menu menu, MenuAction action, int param1, int param2)
  896. {
  897. switch (action)
  898. {
  899. case MenuAction_Start:
  900. {
  901. // It's important to log anything in any way, the best is printtoserver, but if you just want to log to client to make it easier to get progress done, feel free.
  902. PrintToServer("Displaying menu"); // Log it
  903. }
  904.  
  905. case MenuAction_Display:
  906. {
  907. PrintToServer("Client %d was sent menu with panel %x", param1, param2); // Log so you can check if it gets sent.
  908. }
  909.  
  910. case MenuAction_Select:
  911. {
  912. char sInfo[32];
  913. menu.GetItem(param2, sInfo, sizeof(sInfo));
  914.  
  915. switch (param2)
  916. {
  917. case 0:
  918. {
  919. int iSpawnerClassBlu = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
  920. g_iSpawnersMaxRockets[iSpawnerClassBlu] = 1;
  921.  
  922. int iSpawnerClassRed = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
  923. g_iSpawnersMaxRockets[iSpawnerClassRed] = 1;
  924.  
  925. CPrintToChatAll("%s %s%N %schanged the max rockets to %s1.", g_strServerChatTag, g_strClientChatColor, param1, g_strMainChatColor, g_strKeywordChatColor);
  926. }
  927. case 1:
  928. {
  929. int iSpawnerClassBlu = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
  930. g_iSpawnersMaxRockets[iSpawnerClassBlu] = 2;
  931.  
  932. int iSpawnerClassRed = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
  933. g_iSpawnersMaxRockets[iSpawnerClassRed] = 2;
  934.  
  935. CPrintToChatAll("%s %s%N %schanged the max rockets to %s2.", g_strServerChatTag, g_strClientChatColor, param1, g_strMainChatColor, g_strKeywordChatColor);
  936. }
  937. case 2:
  938. {
  939. int iSpawnerClassBlu = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
  940. g_iSpawnersMaxRockets[iSpawnerClassBlu] = 3;
  941.  
  942. int iSpawnerClassRed = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
  943. g_iSpawnersMaxRockets[iSpawnerClassRed] = 3;
  944.  
  945. CPrintToChatAll("%s %s%N %schanged the max rockets to %s3.", g_strServerChatTag, g_strClientChatColor, param1, g_strMainChatColor, g_strKeywordChatColor);
  946. }
  947. case 3:
  948. {
  949. int iSpawnerClassBlu = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
  950. g_iSpawnersMaxRockets[iSpawnerClassBlu] = 4;
  951.  
  952. int iSpawnerClassRed = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
  953. g_iSpawnersMaxRockets[iSpawnerClassRed] = 4;
  954.  
  955. CPrintToChatAll("%s %s%N %schanged the max rockets to %s4.", g_strServerChatTag, g_strKeywordChatColor, param1, g_strMainChatColor, g_strKeywordChatColor);
  956. }
  957. case 4:
  958. {
  959. int iSpawnerClassBlu = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
  960. g_iSpawnersMaxRockets[iSpawnerClassBlu] = 5;
  961.  
  962. int iSpawnerClassRed = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
  963. g_iSpawnersMaxRockets[iSpawnerClassRed] = 5;
  964.  
  965. CPrintToChatAll("%s %s%N %schanged the max rockets to %s5.", g_strServerChatTag, g_strKeywordChatColor, param1, g_strMainChatColor, g_strKeywordChatColor);
  966. }
  967. }
  968. }
  969.  
  970. case MenuAction_Cancel:
  971. {
  972. PrintToServer("Client %d's menu was cancelled for reason %d", param1, param2); // Logging once again.
  973. }
  974.  
  975. case MenuAction_End:
  976. {
  977. delete menu;
  978. }
  979.  
  980. case MenuAction_DrawItem:
  981. {
  982. int style;
  983. char info[32];
  984. menu.GetItem(param2, info, sizeof(info), style);
  985. }
  986.  
  987. case MenuAction_DisplayItem:
  988. {
  989. char info[32];
  990. menu.GetItem(param2, info, sizeof(info));
  991. }
  992. }
  993. }
  994.  
  995. public int DodgeballAdminRocketSpeed_Handler(Menu menu, MenuAction action, int param1, int param2)
  996. {
  997. switch (action)
  998. {
  999. case MenuAction_Start:
  1000. {
  1001. // It's important to log anything in any way, the best is printtoserver, but if you just want to log to client to make it easier to get progress done, feel free.
  1002. PrintToServer("Displaying menu"); // Log it
  1003. }
  1004.  
  1005. case MenuAction_Display:
  1006. {
  1007. PrintToServer("Client %d was sent menu with panel %x", param1, param2); // Log so you can check if it gets sent.
  1008. }
  1009.  
  1010. case MenuAction_Select:
  1011. {
  1012. char sInfo[32];
  1013. menu.GetItem(param2, sInfo, sizeof(sInfo));
  1014. float kvSpeed = g_fSavedSpeed;
  1015. float kvSpeedIncrement = g_fSavedSpeedIncrement;
  1016.  
  1017. switch (param2)
  1018. {
  1019. case 0:
  1020. {
  1021. int iSpawnerClassBlu = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
  1022. int iSpawnerClassRed = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
  1023. int iClassRed = GetRandomRocketClass(iSpawnerClassRed);
  1024. int iClassBlu = GetRandomRocketClass(iSpawnerClassBlu);
  1025.  
  1026. g_fRocketSpeed[iClassRed] = kvSpeed / 2;
  1027. g_fRocketClassSpeedIncrement[iClassRed] = kvSpeedIncrement / 2;
  1028.  
  1029. g_fRocketSpeed[iClassBlu] = kvSpeed / 2;
  1030. g_fRocketClassSpeedIncrement[iClassBlu] = kvSpeedIncrement / 2;
  1031.  
  1032. CPrintToChatAll("%s %s%N %schanged the rocket speed to %s25%% (Slow)", g_strServerChatTag, g_strClientChatColor, param1, g_strMainChatColor, g_strKeywordChatColor);
  1033. }
  1034. case 1:
  1035. {
  1036. int iSpawnerClassBlu = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
  1037. int iSpawnerClassRed = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
  1038. int iClassRed = GetRandomRocketClass(iSpawnerClassRed);
  1039. int iClassBlu = GetRandomRocketClass(iSpawnerClassBlu);
  1040.  
  1041. g_fRocketSpeed[iClassRed] = kvSpeed;
  1042. g_fRocketClassSpeedIncrement[iClassRed] = kvSpeedIncrement;
  1043.  
  1044. g_fRocketSpeed[iClassBlu] = kvSpeed;
  1045. g_fRocketClassSpeedIncrement[iClassBlu] = kvSpeedIncrement;
  1046.  
  1047. CPrintToChatAll("%s %s%N %schanged the rocket speed to %s50%% (Normal)", g_strServerChatTag, g_strClientChatColor, param1, g_strMainChatColor, g_strKeywordChatColor);
  1048. }
  1049. case 2:
  1050. {
  1051. int iSpawnerClassBlu = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
  1052. int iSpawnerClassRed = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
  1053. int iClassRed = GetRandomRocketClass(iSpawnerClassRed);
  1054. int iClassBlu = GetRandomRocketClass(iSpawnerClassBlu);
  1055.  
  1056. g_fRocketSpeed[iClassRed] = kvSpeed * 2;
  1057. g_fRocketClassSpeedIncrement[iClassRed] = kvSpeedIncrement * 2;
  1058.  
  1059. g_fRocketSpeed[iClassBlu] = kvSpeed * 2;
  1060. g_fRocketClassSpeedIncrement[iClassBlu] = kvSpeedIncrement * 2;
  1061.  
  1062. CPrintToChatAll("%s %s%N %schanged the rocket speed to %s75%% (Fast)", g_strServerChatTag, g_strClientChatColor, param1, g_strMainChatColor, g_strKeywordChatColor);
  1063. }
  1064. case 3:
  1065. {
  1066. int iSpawnerClassBlu = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
  1067. int iSpawnerClassRed = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
  1068. int iClassRed = GetRandomRocketClass(iSpawnerClassRed);
  1069. int iClassBlu = GetRandomRocketClass(iSpawnerClassBlu);
  1070.  
  1071. g_fRocketSpeed[iClassRed] = kvSpeed * 3;
  1072. g_fRocketClassSpeedIncrement[iClassRed] = kvSpeedIncrement * 3;
  1073.  
  1074. g_fRocketSpeed[iClassBlu] = kvSpeed * 3;
  1075. g_fRocketClassSpeedIncrement[iClassBlu] = kvSpeedIncrement * 3;
  1076.  
  1077. CPrintToChatAll("%s %s%N %schanged the rocket speed to %s100%% (Silly Fast)", g_strServerChatTag, g_strClientChatColor, param1, g_strMainChatColor, g_strKeywordChatColor);
  1078. }
  1079. }
  1080. }
  1081.  
  1082. case MenuAction_Cancel:
  1083. {
  1084. PrintToServer("Client %d's menu was cancelled for reason %d", param1, param2); // Logging once again.
  1085. }
  1086.  
  1087. case MenuAction_End:
  1088. {
  1089. delete menu;
  1090. }
  1091.  
  1092. case MenuAction_DrawItem:
  1093. {
  1094. int style;
  1095. char info[32];
  1096. menu.GetItem(param2, info, sizeof(info), style);
  1097. }
  1098.  
  1099. case MenuAction_DisplayItem:
  1100. {
  1101. char info[32];
  1102. menu.GetItem(param2, info, sizeof(info));
  1103. }
  1104. }
  1105. }
  1106.  
  1107. public int DodgeballAdminRocketClass_Handler(Menu menu, MenuAction action, int param1, int param2)
  1108. {
  1109. switch (action)
  1110. {
  1111. case MenuAction_Start:
  1112. {
  1113. // It's important to log anything in any way, the best is printtoserver, but if you just want to log to client to make it easier to get progress done, feel free.
  1114. PrintToServer("Displaying menu"); // Log it
  1115. }
  1116.  
  1117. case MenuAction_Display:
  1118. {
  1119. PrintToServer("Client %d was sent menu with panel %x", param1, param2); // Log so you can check if it gets sent.
  1120. }
  1121.  
  1122. case MenuAction_Select:
  1123. {
  1124. char sInfo[32];
  1125. menu.GetItem(param2, sInfo, sizeof(sInfo));
  1126.  
  1127. SetMainRocketClass(param2, false, param1);
  1128. }
  1129.  
  1130. case MenuAction_Cancel:
  1131. {
  1132. PrintToServer("Client %d's menu was cancelled for reason %d", param1, param2); // Logging once again.
  1133. }
  1134.  
  1135. case MenuAction_End:
  1136. {
  1137. delete menu;
  1138. }
  1139.  
  1140. case MenuAction_DrawItem:
  1141. {
  1142. int style;
  1143. char info[32];
  1144. menu.GetItem(param2, info, sizeof(info), style);
  1145. }
  1146.  
  1147. case MenuAction_DisplayItem:
  1148. {
  1149. char info[32];
  1150. menu.GetItem(param2, info, sizeof(info));
  1151. }
  1152. }
  1153. }
  1154.  
  1155. //__ __ _
  1156. //\ \ / /__| |_ ___ ___
  1157. // \ V / _ \ _/ -_|_-<
  1158. // \_/\___/\__\___/__/
  1159.  
  1160. public Action Command_VoteRocketClass(int client, int args) {
  1161. if (!g_strSavedClassName[0])
  1162. {
  1163. g_bVoteClassEnabled = false;
  1164. CPrintToChat(client, "%s %sNo main rocket class detected, voting for rocket class %sdisabled.", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor);
  1165. return Plugin_Handled;
  1166. }
  1167. else g_bVoteClassEnabled = true;
  1168.  
  1169. if(!g_bVoteClassEnabled) {
  1170. CReplyToCommand(client, "%s %sVoting for rocket class is %snot enabled.", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor);
  1171. return Plugin_Handled;
  1172. }
  1173.  
  1174. if(!g_bCanVoteClass) {
  1175. CReplyToCommand(client,"%s %sYou cannot vote at this time (%s%ds %sleft).", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor, GetConVarInt(g_hCvarVoteClassCooldown) - (GetTime() - g_iTimeVoted), g_strMainChatColor);
  1176. return Plugin_Handled;
  1177. }
  1178.  
  1179. g_iClassVotesRequired = RoundToCeil(GetTotalClientCount() * GetConVarFloat(g_hCvarVoteClassPercentage));
  1180.  
  1181. if(g_bClassVoted[client]) {
  1182. CReplyToCommand(client, "%s %sYou have %salready %svoted", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor, g_strMainChatColor);
  1183. return Plugin_Handled;
  1184. }
  1185.  
  1186. if(IsVoteInProgress()) {
  1187. CReplyToCommand(client, "%s %sA vote is currently %sin progress", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor);
  1188. return Plugin_Handled;
  1189. }
  1190.  
  1191. g_iClassVotes++;
  1192. g_bClassVoted[client] = true;
  1193.  
  1194. CPrintToChatAll("%s %s%N %swants to change the rocket class (%s%d/%d%s votes)", g_strServerChatTag, g_strClientChatColor, client, g_strMainChatColor, g_strKeywordChatColor, g_iClassVotes, g_iClassVotesRequired, g_strMainChatColor);
  1195.  
  1196. if(g_iClassVotes >= g_iClassVotesRequired) {
  1197. CreateTimer(2.0, Timer_StartRocketClassVote);
  1198. g_bCanVoteClass = false;
  1199.  
  1200. g_iClassVotes = 0;
  1201. for(int i = 0; i < sizeof(g_bClassVoted); i++) {
  1202. g_bClassVoted[i] = false;
  1203. }
  1204.  
  1205. CreateTimer(GetConVarFloat(g_hCvarVoteClassCooldown), Timer_AllowRocketClassVote);
  1206. }
  1207.  
  1208. return Plugin_Handled;
  1209. }
  1210.  
  1211. /*
  1212. **����������������������������������������������������������������������������������
  1213. ** __ ___ __
  1214. ** / |/ /___ _____ ____ _____ ____ ____ ___ ___ ____ / /_
  1215. ** / /|_/ / __ `/ __ \/ __ `/ __ `/ _ \/ __ `__ \/ _ \/ __ \/ __/
  1216. ** / / / / /_/ / / / / /_/ / /_/ / __/ / / / / / __/ / / / /_
  1217. ** /_/ /_/\__,_/_/ /_/\__,_/\__, /\___/_/ /_/ /_/\___/_/ /_/\__/
  1218. ** /____/
  1219. **����������������������������������������������������������������������������������
  1220. */
  1221.  
  1222. // ___ _
  1223. // / __|___ _ _ ___ _ _ __ _| |
  1224. // | (_ / -_) ' \/ -_) '_/ _` | |
  1225. // \___\___|_||_\___|_| \__,_|_|
  1226.  
  1227. /* IsDodgeBallMap()
  1228. **
  1229. ** Checks if the current map is a dodgeball map.
  1230. ** -------------------------------------------------------------------------- */
  1231. bool IsDodgeBallMap()
  1232. {
  1233. char strMap[64];
  1234. GetCurrentMap(strMap, sizeof(strMap));
  1235. return StrContains(strMap, "tfdb_", false) == 0;
  1236. }
  1237.  
  1238. /* EnableDodgeBall()
  1239. **
  1240. ** Enables and hooks all the required events.
  1241. ** -------------------------------------------------------------------------- */
  1242. void EnableDodgeBall()
  1243. {
  1244. if (g_bEnabled == false)
  1245. {
  1246. // Parse configuration files
  1247. char strMapName[64]; GetCurrentMap(strMapName, sizeof(strMapName));
  1248. char strMapFile[PLATFORM_MAX_PATH]; Format(strMapFile, sizeof(strMapFile), "%s.cfg", strMapName);
  1249. ParseConfigurations();
  1250. ParseConfigurations(strMapFile);
  1251.  
  1252. ServerCommand("tf_dodgeball_rbmax %f", GetConVarFloat(g_hMaxBouncesConVar));
  1253.  
  1254. // Check if we have all the required information
  1255. if (g_iRocketClassCount == 0)
  1256. SetFailState("No rocket class defined.");
  1257.  
  1258. if (g_iSpawnersCount == 0)
  1259. SetFailState("No spawner class defined.");
  1260.  
  1261. if (g_iDefaultRedSpawner == -1)
  1262. SetFailState("No spawner class definition for the Red spawners exists in the config file.");
  1263.  
  1264. if (g_iDefaultBluSpawner == -1)
  1265. SetFailState("No spawner class definition for the Blu spawners exists in the config file.");
  1266.  
  1267. // Hook events and info_target outputs.
  1268. HookEvent("object_deflected", Event_ObjectDeflected);
  1269. HookEvent("teamplay_round_start", OnRoundStart, EventHookMode_PostNoCopy);
  1270. HookEvent("teamplay_setup_finished", OnSetupFinished, EventHookMode_PostNoCopy);
  1271. HookEvent("teamplay_round_win", OnRoundEnd, EventHookMode_PostNoCopy);
  1272. HookEvent("player_spawn", OnPlayerSpawn, EventHookMode_Post);
  1273. HookEvent("player_death", OnPlayerDeath, EventHookMode_Pre);
  1274. HookEvent("post_inventory_application", OnPlayerInventory, EventHookMode_Post);
  1275. HookEvent("teamplay_broadcast_audio", OnBroadcastAudio, EventHookMode_Pre);
  1276.  
  1277.  
  1278.  
  1279. // Precache sounds
  1280. PrecacheSound(SOUND_DEFAULT_SPAWN, true);
  1281. PrecacheSound(SOUND_DEFAULT_BEEP, true);
  1282. PrecacheSound(SOUND_DEFAULT_ALERT, true);
  1283. PrecacheSound(SOUND_DEFAULT_SPEEDUPALERT, true);
  1284. if (g_bMusicEnabled == true)
  1285. {
  1286. if (g_bMusic[Music_RoundStart])PrecacheSoundEx(g_strMusic[Music_RoundStart], true, true);
  1287. if (g_bMusic[Music_RoundWin])PrecacheSoundEx(g_strMusic[Music_RoundWin], true, true);
  1288. if (g_bMusic[Music_RoundLose])PrecacheSoundEx(g_strMusic[Music_RoundLose], true, true);
  1289. if (g_bMusic[Music_Gameplay])PrecacheSoundEx(g_strMusic[Music_Gameplay], true, true);
  1290. }
  1291.  
  1292. // Precache particles
  1293. PrecacheParticle(PARTICLE_NUKE_1);
  1294. PrecacheParticle(PARTICLE_NUKE_2);
  1295. PrecacheParticle(PARTICLE_NUKE_3);
  1296. PrecacheParticle(PARTICLE_NUKE_4);
  1297. PrecacheParticle(PARTICLE_NUKE_5);
  1298. PrecacheParticle(PARTICLE_NUKE_COLLUMN);
  1299.  
  1300. // Precache rocket resources
  1301. for (int i = 0; i < g_iRocketClassCount; i++)
  1302. {
  1303. RocketFlags iFlags = g_iRocketClassFlags[i];
  1304. if (TestFlags(iFlags, RocketFlag_CustomModel))PrecacheModelEx(g_strRocketClassModel[i], true, true);
  1305. if (TestFlags(iFlags, RocketFlag_CustomSpawnSound))PrecacheSoundEx(g_strRocketClassSpawnSound[i], true, true);
  1306. if (TestFlags(iFlags, RocketFlag_CustomBeepSound))PrecacheSoundEx(g_strRocketClassBeepSound[i], true, true);
  1307. if (TestFlags(iFlags, RocketFlag_CustomAlertSound))PrecacheSoundEx(g_strRocketClassAlertSound[i], true, true);
  1308. }
  1309.  
  1310. // Execute enable config file
  1311. char strCfgFile[64]; GetConVarString(g_hCvarEnableCfgFile, strCfgFile, sizeof(strCfgFile));
  1312. ServerCommand("exec \"%s\"", strCfgFile);
  1313.  
  1314. // Done.
  1315. g_bEnabled = true;
  1316. g_bRoundStarted = false;
  1317. g_iRoundCount = 0;
  1318. }
  1319. }
  1320.  
  1321. /* DisableDodgeBall()
  1322. **
  1323. ** Disables all hooks and frees arrays.
  1324. ** -------------------------------------------------------------------------- */
  1325. void DisableDodgeBall()
  1326. {
  1327. if (g_bEnabled == true)
  1328. {
  1329. // Clean up everything
  1330. DestroyRockets();
  1331. DestroyRocketClasses();
  1332. DestroySpawners();
  1333. // if (g_hLogicTimer != INVALID_HANDLE)KillTimer(g_hLogicTimer);
  1334. // g_hLogicTimer = INVALID_HANDLE;
  1335. IsOnGameFrame = false;
  1336.  
  1337. // Disable music
  1338. g_bMusic[Music_RoundStart] =
  1339. g_bMusic[Music_RoundWin] =
  1340. g_bMusic[Music_RoundLose] =
  1341. g_bMusic[Music_Gameplay] = false;
  1342.  
  1343. // Unhook events and info_target outputs;
  1344. UnhookEvent("teamplay_round_start", OnRoundStart, EventHookMode_PostNoCopy);
  1345. UnhookEvent("teamplay_setup_finished", OnSetupFinished, EventHookMode_PostNoCopy);
  1346. UnhookEvent("teamplay_round_win", OnRoundEnd, EventHookMode_PostNoCopy);
  1347. UnhookEvent("player_spawn", OnPlayerSpawn, EventHookMode_Post);
  1348. UnhookEvent("player_death", OnPlayerDeath, EventHookMode_Pre);
  1349. UnhookEvent("post_inventory_application", OnPlayerInventory, EventHookMode_Post);
  1350. UnhookEvent("teamplay_broadcast_audio", OnBroadcastAudio, EventHookMode_Pre);
  1351.  
  1352. // Execute enable config file
  1353. char strCfgFile[64]; GetConVarString(g_hCvarDisableCfgFile, strCfgFile, sizeof(strCfgFile));
  1354. ServerCommand("exec \"%s\"", strCfgFile);
  1355.  
  1356. // Done.
  1357. g_bEnabled = false;
  1358. g_bRoundStarted = false;
  1359. g_iRoundCount = 0;
  1360. }
  1361. }
  1362. public void OnClientPutInServer(int clientId)
  1363. {
  1364. if (GetConVarBool(g_hCvarAirBlastCommandEnabled))
  1365. {
  1366. firstJoined[clientId] = true;
  1367. }
  1368. if (GetConVarBool(g_hCvarPreventTauntKillEnabled))
  1369. {
  1370. SDKHook(clientId, SDKHook_OnTakeDamage, TauntCheck);
  1371. }
  1372.  
  1373.  
  1374. SDKHook(clientId, SDKHook_OnTakeDamage, OnTakeDamage);
  1375. SetGodmodeState();
  1376.  
  1377.  
  1378. }
  1379.  
  1380.  
  1381.  
  1382. public void OnClientConnected(int client)
  1383. {
  1384. if (IsFakeClient(client)) return;
  1385.  
  1386. g_bClassVoted[client] = false;
  1387. g_iClassVoters++;
  1388. g_iClassVotesRequired = RoundToCeil(GetTotalClientCount() * GetConVarFloat(g_hCvarVoteClassPercentage));
  1389. SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage);
  1390. SetGodmodeState();
  1391. }
  1392.  
  1393. public void OnClientDisconnect(int client)
  1394. {
  1395. if(IsFakeClient(client)) return;
  1396.  
  1397. if (GetConVarBool(g_hCvarPreventTauntKillEnabled))
  1398. {
  1399. SDKUnhook(client, SDKHook_OnTakeDamage, TauntCheck);
  1400. }
  1401.  
  1402. if (GetConVarBool(g_hCvarStealPrevention))
  1403. {
  1404. bStealArray[client][stoleRocket] = false;
  1405. bStealArray[client][rocketsStolen] = 0;
  1406. }
  1407.  
  1408. if(g_bClassVoted[client])
  1409. {
  1410. g_iClassVotes--;
  1411. }
  1412.  
  1413. g_iClassVoters--;
  1414. g_iClassVotesRequired = RoundToCeil(GetTotalClientCount() * GetConVarFloat(g_hCvarVoteClassPercentage));
  1415.  
  1416. if (g_iClassVotes >= g_iClassVotesRequired && g_bVoteClassEnabled && g_iClassVoters != 0)
  1417. {
  1418. CreateTimer(2.0, Timer_StartRocketClassVote);
  1419. }
  1420. SDKUnhook(client, SDKHook_OnTakeDamage, OnTakeDamage);
  1421. SetGodmodeState();
  1422. }
  1423.  
  1424. /* OnObjectDeflected
  1425. **
  1426. **
  1427. ** Check if client is human, don't airblast if bool is false
  1428. ** -------------------------------------------------------------------------- */
  1429. public Action Event_ObjectDeflected(Handle event, const char[] name, bool dontBroadcast)
  1430. {
  1431. if (GetConVarBool(g_hCvarAirBlastCommandEnabled))
  1432. {
  1433. int object1 = GetEventInt(event, "object_entindex");
  1434. if ((object1 >= 1) && (object1 <= MaxClients))
  1435. {
  1436. if (Airblast[object1])
  1437. {
  1438. float Vel[3];
  1439. TeleportEntity(object1, NULL_VECTOR, NULL_VECTOR, Vel); // Stops knockback
  1440. TF2_RemoveCondition(object1, TFCond_Dazed); // Stops slowdown
  1441. SetEntPropVector(object1, Prop_Send, "m_vecPunchAngle", Vel);
  1442. SetEntPropVector(object1, Prop_Send, "m_vecPunchAngleVel", Vel); // Stops screen shake
  1443. }
  1444. }
  1445. }
  1446. }
  1447.  
  1448. /* IsValidAliveClient()
  1449. **
  1450. ** Check if the client is valid and alive/ingame
  1451. ** -------------------------------------------------------------------------- */
  1452. stock bool IsValidAliveClient(int client)
  1453. {
  1454. if(client <= 0 || client > MaxClients || !IsClientConnected(client) || !IsClientInGame(client) || !IsPlayerAlive(client))
  1455. {
  1456. return false;
  1457. }
  1458. return true;
  1459. }
  1460.  
  1461. /* GetAlivePlayersCount()
  1462. **
  1463. ** Get alive players of a team (ignoring one)
  1464. ** -------------------------------------------------------------------------- */
  1465. stock GetAlivePlayersCount(team,ignore=-1)
  1466. {
  1467. int count = 0, i;
  1468.  
  1469. for( i = 1; i <= MaxClients; i++ )
  1470. {
  1471. if(IsValidAliveClient(i) && GetClientTeam(i) == team && i != ignore)
  1472. {
  1473. count++;
  1474. }
  1475. }
  1476. return count;
  1477. }
  1478.  
  1479. /* GetAlivePlayersCount()
  1480. **
  1481. ** Get last player of a team (ignoring one), asuming that GetAlivePlayersCountwas used before.
  1482. ** -------------------------------------------------------------------------- */
  1483. stock GetLastPlayer(team,ignore=-1)
  1484. {
  1485. for(int i = 1; i <= MaxClients; i++ )
  1486. {
  1487. if(IsValidAliveClient(i) && GetClientTeam(i) == team && i != ignore)
  1488. {
  1489. return i;
  1490. }
  1491. }
  1492. return -1;
  1493. }
  1494.  
  1495. public Action Timer_HudName(Handle hTimer)
  1496. {
  1497. SetHudTextParams(0, 0, 0.5, 255, 20, 40, 255, 0, 6.0, 0.1, 0.2);
  1498. for (int iClient = 1; iClient <= MaxClients; iClient++)
  1499. {
  1500. if (IsValidClient(iClient) && !IsFakeClient(iClient))
  1501. {
  1502. ShowSyncHudText(iClient, g_hNameHud, "%s", g_strNameHud);
  1503. }
  1504. }
  1505. }
  1506.  
  1507. public Action Timer_Hud1v1(Handle hTimer)
  1508. {
  1509. SetHudTextParams(-1.0, 0.7,7.0,0,255,255,255, 1, 3.0, 1.5, 1.5);
  1510. for (int iClient = 1; iClient <= MaxClients; iClient++)
  1511. {
  1512. if (IsValidClient(iClient) && !IsFakeClient(iClient) && g_iRocketSpeed != 0 && GetAlivePlayersCount(TEAM_BLUE,-1) == 1 && GetAlivePlayersCount(TEAM_RED,-1) == 1)
  1513. {
  1514. ShowSyncHudText(iClient, g_h1v1Hud, "%N and %N are the last players standing !", GetLastPlayer(TEAM_RED), GetLastPlayer(TEAM_BLUE));
  1515. }
  1516. }
  1517.  
  1518. }
  1519.  
  1520.  
  1521.  
  1522. public Action Truc(Handle timer)
  1523. {
  1524. CloseHandle(g_h1v1Hud);
  1525. }
  1526.  
  1527. // ___ _
  1528. // / __|__ _ _ __ ___ _ __| |__ _ _ _
  1529. // | (_ / _` | ' \/ -_) '_ \ / _` | || |
  1530. // \___\__,_|_|_|_\___| .__/_\__,_|\_, |
  1531. // |_| |__/
  1532.  
  1533. /* OnRoundStart()
  1534. **
  1535. ** At round start, do something?
  1536. ** -------------------------------------------------------------------------- */
  1537. public Action OnRoundStart(Handle hEvent, char[] strEventName, bool bDontBroadcast)
  1538. {
  1539. SetGodmodeState();
  1540. if (GetConVarBool(g_hCvarStealPrevention))
  1541. {
  1542. for (int i = 0; i <= MaxClients; i++)
  1543. {
  1544. bStealArray[i][stoleRocket] = false;
  1545. bStealArray[i][rocketsStolen] = 0;
  1546. }
  1547. }
  1548.  
  1549. if (g_bMusic[Music_RoundStart])
  1550. {
  1551. EmitSoundToAll(g_strMusic[Music_RoundStart]);
  1552. }
  1553. g_iRocketSpeed = 0;
  1554. if (g_hTimerHud != INVALID_HANDLE)
  1555. {
  1556. KillTimer(g_hTimerHud);
  1557. g_hTimerHud = INVALID_HANDLE;
  1558. }
  1559. g_hTimerHud = CreateTimer(0.3, Timer_HudSpeed, _, TIMER_REPEAT);
  1560. CreateTimer(0.1, Timer_Hud1v1, _, TIMER_REPEAT);
  1561. CreateTimer(0.9, Timer_HudName, _, TIMER_REPEAT);
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567. }
  1568.  
  1569.  
  1570. /* OnSetupFinished()
  1571. **
  1572. ** When the setup finishes, populate the spawn points arrays and create the
  1573. ** Dodgeball game logic timer.
  1574. ** -------------------------------------------------------------------------- */
  1575. public Action OnSetupFinished(Handle hEvent, char[] strEventName, bool bDontBroadcast)
  1576. {
  1577. if ((g_bEnabled == true) && (BothTeamsPlaying() == true))
  1578. {
  1579. PopulateSpawnPoints();
  1580.  
  1581. if (g_iLastDeadTeam == 0)
  1582. {
  1583. g_iLastDeadTeam = GetURandomIntRange(view_as<int>(TFTeam_Red), view_as<int>(TFTeam_Blue));
  1584. }
  1585. if (!IsValidClient(g_iLastDeadClient))g_iLastDeadClient = 0;
  1586.  
  1587. //g_hLogicTimer = CreateTimer(FPS_LOGIC_INTERVAL, OnDodgeBallGameFrame, _, TIMER_REPEAT);
  1588. IsOnGameFrame = true;
  1589. g_iPlayerCount = CountAlivePlayers();
  1590. g_iRocketsFired = 0;
  1591. g_iCurrentRedSpawn = 0;
  1592. g_iCurrentBluSpawn = 0;
  1593. g_fNextSpawnTime = GetGameTime();
  1594. g_bRoundStarted = true;
  1595. g_iRoundCount++;
  1596. }
  1597. }
  1598.  
  1599. /* OnRoundEnd()
  1600. **
  1601. ** At round end, stop the Dodgeball game logic timer and destroy the remaining
  1602. ** rockets.
  1603. ** -------------------------------------------------------------------------- */
  1604. public Action OnRoundEnd(Handle hEvent, char[] strEventName, bool bDontBroadcast)
  1605. {
  1606. if (g_hTimerHud != INVALID_HANDLE)
  1607. {
  1608. KillTimer(g_hTimerHud);
  1609. g_hTimerHud = INVALID_HANDLE;
  1610. }
  1611. // if (g_hLogicTimer != INVALID_HANDLE)
  1612. // {
  1613. // KillTimer(g_hLogicTimer);
  1614. // g_hLogicTimer = INVALID_HANDLE;
  1615. // }
  1616.  
  1617. IsOnGameFrame = false;
  1618.  
  1619.  
  1620. if (GetConVarBool(g_hCvarAirBlastCommandEnabled))
  1621. {
  1622. for (int i = 0; i < MAXPLAYERS + 1; i++)
  1623. {
  1624. firstJoined[i] = false;
  1625. }
  1626. }
  1627. if (g_bMusicEnabled == true)
  1628. {
  1629. if (g_bUseWebPlayer)
  1630. {
  1631. for (int iClient = 1; iClient <= MaxClients; iClient++)
  1632. {
  1633. if (IsValidClient(iClient))
  1634. {
  1635. ShowHiddenMOTDPanel(iClient, "MusicPlayerStop", "http://0.0.0.0/");
  1636. if (!IsFakeClient(iClient))
  1637. {
  1638. ClearSyncHud(iClient, g_hHud);
  1639. }
  1640. }
  1641. }
  1642. }
  1643. else if (g_bMusic[Music_Gameplay])
  1644. {
  1645. StopSoundToAll(SNDCHAN_MUSIC, g_strMusic[Music_Gameplay]);
  1646. }
  1647. }
  1648.  
  1649. DestroyRockets();
  1650. g_bRoundStarted = false;
  1651. }
  1652.  
  1653. public Action Command_ToggleAirblast(int clientId, int args)
  1654. {
  1655. if (GetConVarBool(g_hCvarAirBlastCommandEnabled))
  1656. {
  1657. char arg[128];
  1658.  
  1659. if (args > 1)
  1660. {
  1661. ReplyToCommand(clientId, "[SM] %s", USAGE);
  1662. return Plugin_Handled;
  1663. }
  1664.  
  1665. if (args == 0)
  1666. {
  1667. preventAirblast(clientId, !abPrevention[clientId]);
  1668. }
  1669. else if (args == 1)
  1670. {
  1671. GetCmdArg(1, arg, sizeof(arg));
  1672.  
  1673. if (strcmp(arg, "0") == 0)
  1674. {
  1675. preventAirblast(clientId, false);
  1676. }
  1677. else if (strcmp(arg, "1") == 0)
  1678. {
  1679. preventAirblast(clientId, true);
  1680. }
  1681. else
  1682. {
  1683. ReplyToCommand(clientId, "[SM] %s", USAGE);
  1684. return Plugin_Handled;
  1685. }
  1686. }
  1687.  
  1688. if (abPrevention[clientId])
  1689. {
  1690. ReplyToCommand(clientId, "[SM] %s", "Airblast Prevention Enabled");
  1691. }
  1692. else
  1693. {
  1694. ReplyToCommand(clientId, "[SM] %s", "Airblast Prevention Disabled");
  1695. }
  1696. }
  1697.  
  1698. if (!GetConVarBool(g_hCvarAirBlastCommandEnabled))
  1699. {
  1700. ReplyToCommand(clientId, "[SM] %s", "Airblast Prevention is disabled on this server.");
  1701. preventAirblast(clientId, false);
  1702. }
  1703. return Plugin_Handled;
  1704. }
  1705.  
  1706. public Action Command_PostCurrentRocketClass(int client, int args)
  1707. {
  1708. if (args > 1)
  1709. {
  1710. ReplyToCommand(client, "[SM] %s", "Usage: sm_currentrocket");
  1711. return Plugin_Handled;
  1712. }
  1713.  
  1714. if (!g_strSavedClassName[0])
  1715. {
  1716. CPrintToChat(client, "%s %sCurrent Rocket: %sMultiple", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor);
  1717. return Plugin_Handled;
  1718. }
  1719. CPrintToChatAll("%s %sCurrent Rocket: %s%s", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor, g_strSavedClassName);
  1720.  
  1721. return Plugin_Handled;
  1722. }
  1723.  
  1724.  
  1725. /* OnPlayerSpawn()
  1726. **
  1727. ** When the player spawns, force class to Pyro.
  1728. ** -------------------------------------------------------------------------- */
  1729. public Action OnPlayerSpawn(Handle hEvent, char[] strEventName, bool bDontBroadcast)
  1730. {
  1731. int iClient = GetClientOfUserId(GetEventInt(hEvent, "userid"));
  1732. int clientId = GetClientOfUserId(GetEventInt(hEvent, "userid"));
  1733. //g_stolen[iClient] = 0;
  1734.  
  1735. if (!IsValidClient(iClient)) return;
  1736.  
  1737. TFClassType iClass = TF2_GetPlayerClass(iClient);
  1738. if (!(iClass == TFClass_Pyro || iClass == view_as<TFClassType>(TFClass_Unknown)))
  1739. {
  1740. TF2_SetPlayerClass(iClient, TFClass_Pyro, false, true);
  1741. TF2_RespawnPlayer(iClient);
  1742. }
  1743.  
  1744. for (int i = MaxClients; i; --i)
  1745. {
  1746. if (IsClientInGame(i) && IsPlayerAlive(i))
  1747. SetEntPropEnt(i, Prop_Data, "m_hActiveWeapon", GetPlayerWeaponSlot(i, TFWeaponSlot_Primary));
  1748. }
  1749.  
  1750. if (!GetConVarBool(g_hCvarPyroVisionEnabled))
  1751. {
  1752. return;
  1753. }
  1754. TF2Attrib_SetByName(iClient, PYROVISION_ATTRIBUTE, 1.0);
  1755.  
  1756. if (GetConVarBool(g_hCvarAirBlastCommandEnabled))
  1757. {
  1758. if (firstJoined[clientId])
  1759. {
  1760. //Enable ab prevention when a player joins the server
  1761. abPrevention[clientId] = true;
  1762. }
  1763.  
  1764. preventAirblast(clientId, true);
  1765. }
  1766. }
  1767.  
  1768. /* OnPlayerDeath()
  1769. **
  1770. ** When the player dies, set the last dead team to determine the next
  1771. ** rocket's team.
  1772. ** -------------------------------------------------------------------------- */
  1773. public Action OnPlayerDeath(Handle hEvent, char[] strEventName, bool bDontBroadcast)
  1774. {
  1775. if (g_bRoundStarted == false)
  1776. {
  1777. return;
  1778. }
  1779. int iAttacker = GetClientOfUserId(GetEventInt(hEvent, "attacker"));
  1780. int iVictim = GetClientOfUserId(GetEventInt(hEvent, "userid"));
  1781.  
  1782. if (GetConVarBool(g_hCvarAirBlastCommandEnabled))
  1783. {
  1784. int clientId = GetClientOfUserId(GetEventInt(hEvent, "userid"));
  1785. firstJoined[clientId] = false;
  1786. }
  1787. if (IsValidClient(iVictim))
  1788. {
  1789. if (GetConVarBool(g_hCvarStealPrevention))
  1790. {
  1791. bStealArray[iVictim][stoleRocket] = false;
  1792. bStealArray[iVictim][rocketsStolen] = 0;
  1793. }
  1794.  
  1795. g_iLastDeadClient = iVictim;
  1796. g_iLastDeadTeam = GetClientTeam(iVictim);
  1797.  
  1798. int iInflictor = GetEventInt(hEvent, "inflictor_entindex");
  1799. int iIndex = FindRocketByEntity(iInflictor);
  1800.  
  1801. if (iIndex != -1)
  1802. {
  1803. int iClass = g_iRocketClass[iIndex];
  1804. int iTarget = EntRefToEntIndex(g_iRocketTarget[iIndex]);
  1805. float fSpeed = g_fRocketSpeed[iIndex];
  1806. int iDeflections = g_iRocketDeflections[iIndex];
  1807.  
  1808. if(!GetConVarBool(g_hTouchAnnounce)) {
  1809. if (GetConVarBool(g_hCvarAnnounce)) {
  1810. if (GetConVarBool(g_hCvarDeflectCountAnnounce)) {
  1811. if (iVictim == iTarget) {
  1812. //CPrintToChatAll("%s %s%N %sdied to their rocket travelling %s%i %smph with %s%i %sdeflections!", g_strServerChatTag, g_strKeywordChatColor, g_iLastDeadClient, g_strMainChatColor, g_strKeywordChatColor, g_iRocketSpeed, g_strMainChatColor, g_strKeywordChatColor, iDeflections, g_strMainChatColor);
  1813. CPrintToChatAll("%s %s%N : Speed: %s%i %smph || deflections: %s%i", g_strServerChatTag, iTarget, g_strKeywordChatColor, g_iRocketSpeed, g_strMainChatColor, g_strKeywordChatColor, xDeflections);
  1814. } else {
  1815. CPrintToChatAll("{Orange}%N {DEFAULT}- {Orange}%.15N{DEFAULT}: Speed: {TURQUOISE}%i {DEFAULT}mph || deflections: {TURQUOISE}%i", iTarget, g_iLastDeadClient, g_iRocketSpeed, xDeflections);
  1816. //CPrintToChatAll("%s %s%N %sdied to %s%.15N's %srocket travelling %s%i %smph with %s%i %sdeflections!", g_strServerChatTag, g_strKeywordChatColor, g_iLastDeadClient, g_strMainChatColor, g_strKeywordChatColor, iTarget, g_strMainChatColor, g_strKeywordChatColor, g_iRocketSpeed, g_strMainChatColor, g_strKeywordChatColor, iDeflections, g_strMainChatColor);
  1817. }
  1818. } else {
  1819. //CPrintToChatAll("%s %s%N %sdied to a rocket travelling %s%i %smph!", g_strServerChatTag, g_strKeywordChatColor, g_iLastDeadClient, g_strMainChatColor, g_strKeywordChatColor, g_iRocketSpeed, g_strMainChatColor);
  1820. CPrintToChatAll("{Orange}%N {DEFAULT}- {Orange}%.15N's{DEFAULT}: Speed: {TURQUOISE}%i mph", iTarget, g_iLastDeadClient, g_iRocketSpeed);
  1821. }
  1822. }
  1823. }
  1824.  
  1825. if ((g_iRocketFlags[iIndex] & RocketFlag_OnExplodeCmd) && !(g_iRocketFlags[iIndex] & RocketFlag_Exploded))
  1826. {
  1827. ExecuteCommands(g_hRocketClassCmdsOnExplode[iClass], iClass, iInflictor, iAttacker, iTarget, g_iLastDeadClient, fSpeed, iDeflections);
  1828. g_iRocketFlags[iIndex] |= RocketFlag_Exploded;
  1829. }
  1830.  
  1831. if (TestFlags(g_iRocketFlags[iIndex], RocketFlag_OnKillCmd))
  1832. ExecuteCommands(g_hRocketClassCmdsOnKill[iClass], iClass, iInflictor, iAttacker, iTarget, g_iLastDeadClient, fSpeed, iDeflections);
  1833. }
  1834. }
  1835.  
  1836. SetRandomSeed(view_as<int>(GetGameTime()));
  1837. }
  1838.  
  1839. /* OnPlayerInventory()
  1840. **
  1841. ** Make sure the client only has the flamethrower equipped.
  1842. ** -------------------------------------------------------------------------- */
  1843. public Action OnPlayerInventory(Handle hEvent, char[] strEventName, bool bDontBroadcast)
  1844. {
  1845. int iClient = GetClientOfUserId(GetEventInt(hEvent, "userid"));
  1846. if (!IsValidClient(iClient))return;
  1847.  
  1848. for (int iSlot = 1; iSlot < 5; iSlot++)
  1849. {
  1850. int iEntity = GetPlayerWeaponSlot(iClient, iSlot);
  1851. if (iEntity != -1)RemoveEdict(iEntity);
  1852. }
  1853. }
  1854.  
  1855. /* OnPlayerRunCmd()
  1856. **
  1857. ** Block flamethrower's Mouse1 attack.
  1858. ** -------------------------------------------------------------------------- */
  1859. public Action OnPlayerRunCmd(int iClient, int &iButtons, int &iImpulse, float fVelocity[3], float fAngles[3], int &iWeapon)
  1860. {
  1861. if (g_bEnabled == true)iButtons &= ~IN_ATTACK;
  1862. return Plugin_Continue;
  1863. }
  1864.  
  1865. /* OnBroadcastAudio()
  1866. **
  1867. ** Replaces the broadcasted audio for our custom music files.
  1868. ** -------------------------------------------------------------------------- */
  1869. public Action OnBroadcastAudio(Handle hEvent, char[] strEventName, bool bDontBroadcast)
  1870. {
  1871. if (g_bMusicEnabled == true)
  1872. {
  1873. char strSound[PLATFORM_MAX_PATH];
  1874. GetEventString(hEvent, "sound", strSound, sizeof(strSound));
  1875. int iTeam = GetEventInt(hEvent, "team");
  1876.  
  1877. if (StrEqual(strSound, "Announcer.AM_RoundStartRandom") == true)
  1878. {
  1879. if (g_bUseWebPlayer == false)
  1880. {
  1881. if (g_bMusic[Music_Gameplay])
  1882. {
  1883. EmitSoundToAll(g_strMusic[Music_Gameplay], SOUND_FROM_PLAYER, SNDCHAN_MUSIC);
  1884. return Plugin_Handled;
  1885. }
  1886. }
  1887. else
  1888. {
  1889. for (int iClient = 1; iClient <= MaxClients; iClient++)
  1890. if (IsValidClient(iClient))
  1891. ShowHiddenMOTDPanel(iClient, "MusicPlayerStart", g_strWebPlayerUrl);
  1892.  
  1893. return Plugin_Handled;
  1894. }
  1895. }
  1896. else if (StrEqual(strSound, "Game.YourTeamWon") == true)
  1897. {
  1898. if (g_bMusic[Music_RoundWin])
  1899. {
  1900. for (int iClient = 1; iClient <= MaxClients; iClient++)
  1901. if (IsValidClient(iClient) && (iTeam == GetClientTeam(iClient)))
  1902. EmitSoundToClient(iClient, g_strMusic[Music_RoundWin]);
  1903.  
  1904. return Plugin_Handled;
  1905. }
  1906. }
  1907. else if (StrEqual(strSound, "Game.YourTeamLost") == true)
  1908. {
  1909. if (g_bMusic[Music_RoundLose])
  1910. {
  1911. for (int iClient = 1; iClient <= MaxClients; iClient++)
  1912. if (IsValidClient(iClient) && (iTeam == GetClientTeam(iClient)))
  1913. EmitSoundToClient(iClient, g_strMusic[Music_RoundLose]);
  1914.  
  1915. return Plugin_Handled;
  1916. }
  1917. return Plugin_Handled;
  1918. }
  1919. }
  1920. return Plugin_Continue;
  1921. }
  1922.  
  1923. /* OnGameFrame()
  1924. **
  1925. ** Every tick of the server logic.
  1926. ** -------------------------------------------------------------------------- */
  1927. public void OnGameFrame() {
  1928. if (IsOnGameFrame) {
  1929. // Only if both teams are playing
  1930. if (BothTeamsPlaying() == false) return;
  1931.  
  1932. // Check if we need to fire more rockets.
  1933. if (GetGameTime() >= g_fNextSpawnTime)
  1934. {
  1935. if (g_iLastDeadTeam == view_as<int>(TFTeam_Red))
  1936. {
  1937. int iSpawnerEntity = g_iSpawnPointsRedEntity[g_iCurrentRedSpawn];
  1938. int iSpawnerClass = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
  1939. if (g_iRocketCount < g_iSpawnersMaxRockets[iSpawnerClass])
  1940. {
  1941. CreateRocket(iSpawnerEntity, iSpawnerClass, view_as<int>(TFTeam_Red));
  1942. g_iCurrentRedSpawn = (g_iCurrentRedSpawn + 1) % g_iSpawnPointsRedCount;
  1943. }
  1944. }
  1945. else
  1946. {
  1947. int iSpawnerEntity = g_iSpawnPointsBluEntity[g_iCurrentBluSpawn];
  1948. int iSpawnerClass = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
  1949. if (g_iRocketCount < g_iSpawnersMaxRockets[iSpawnerClass])
  1950. {
  1951. CreateRocket(iSpawnerEntity, iSpawnerClass, view_as<int>(TFTeam_Blue));
  1952. g_iCurrentBluSpawn = (g_iCurrentBluSpawn + 1) % g_iSpawnPointsBluCount;
  1953. }
  1954. }
  1955. }
  1956. // Manage the active rockets
  1957. int iIndex = -1;
  1958. while ((iIndex = FindNextValidRocket(iIndex)) != -1)
  1959. {
  1960. int iEntity = EntRefToEntIndex(g_iRocketEntity[iIndex]);
  1961. int iDeflectionCount = GetEntProp(iEntity, Prop_Send, "m_iDeflected") - 1;
  1962. if ((iDeflectionCount > g_iRocketDeflections[iIndex]) || IsOnTouch) {
  1963. IsOnGameFrame = false;
  1964. CreateTimer(GetTickInterval(), OnDodgeBallGameFrame);
  1965. CreateTimer(GetTickInterval(), SetBack);
  1966. }
  1967. else {
  1968. switch (g_iRocketClassBehaviour[g_iRocketClass[iIndex]])
  1969. {
  1970. case Behaviour_Unknown: { }
  1971. case Behaviour_Homing: { HomingRocketThink(iIndex); }
  1972. }
  1973. }
  1974. }
  1975. }
  1976. }
  1977.  
  1978. /* OnDodgeBallGameFrame()
  1979. **
  1980. ** Every tick of the Dodgeball logic.
  1981. ** -------------------------------------------------------------------------- */
  1982. public Action OnDodgeBallGameFrame(Handle hTimer, any Data)
  1983. {
  1984. // Manage the active rockets
  1985. int iIndex = -1;
  1986. while ((iIndex = FindNextValidRocket(iIndex)) != -1)
  1987. {
  1988. switch (g_iRocketClassBehaviour[g_iRocketClass[iIndex]])
  1989. {
  1990. case Behaviour_Unknown: { }
  1991. case Behaviour_Homing: { HomingRocketThink(iIndex); }
  1992. }
  1993. }
  1994. }
  1995.  
  1996. /*public Action ShowToTarget(int iIndex, int iClient)
  1997. {
  1998. int iParticle = EntRefToEntIndex(g_RocketParticle[iIndex]);
  1999. int iTarget = EntRefToEntIndex(g_iRocketTarget[iIndex]);
  2000.  
  2001. if (!IsValidEntity(iParticle))
  2002. return Plugin_Handled;
  2003.  
  2004. if (!IsValidClient(iTarget))
  2005. return Plugin_Handled;
  2006.  
  2007. if (iClient != iTarget)
  2008. return Plugin_Handled;
  2009.  
  2010. return Plugin_Continue;
  2011. }*/
  2012.  
  2013. public Action Timer_HudSpeed(Handle hTimer)
  2014. {
  2015. if (GetConVarBool(g_hCvarSpeedo))
  2016. {
  2017. SetHudTextParams(-1.0, 0.9, 1.1, 255, 255, 255, 255);
  2018. for (int iClient = 1; iClient <= MaxClients; iClient++)
  2019. {
  2020. if (IsValidClient(iClient) && !IsFakeClient(iClient) && g_iRocketSpeed != 0)
  2021. {
  2022. ShowSyncHudText(iClient, g_hHud, "Speed: %i mph", g_iRocketSpeed);
  2023. }
  2024. }
  2025. }
  2026. }
  2027.  
  2028. public Action Timer_StartRocketClassVote(Handle timer)
  2029. {
  2030. if(!g_bVoteClassEnabled)
  2031. return;
  2032.  
  2033. g_iTimeVoted = GetTime();
  2034.  
  2035. CPrintToChatAll("%s %sVoting for Rocket Class %sstarted!", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor);
  2036.  
  2037. Menu menu = new Menu(Handler_RocketClassVoteMenu);
  2038. menu.SetTitle("Set the Rocket Class:");
  2039.  
  2040. for (int currentClass = 0; currentClass < g_iRocketClassCount; currentClass++)
  2041. {
  2042. char classNumber[16];
  2043. IntToString(currentClass, classNumber, sizeof(classNumber));
  2044. if (StrEqual(g_strSavedClassName, g_strRocketClassLongName[currentClass]))
  2045. {
  2046. char currentClassName[32];
  2047. strcopy(currentClassName, sizeof(currentClassName), "[Current] ");
  2048. StrCat(currentClassName, sizeof(currentClassName), g_strSavedClassName);
  2049. menu.AddItem(classNumber, currentClassName);
  2050. }
  2051. else menu.AddItem(classNumber, g_strRocketClassLongName[currentClass]);
  2052. }
  2053.  
  2054. char nochange[64];
  2055. Format(nochange, 64, "Don't Change");
  2056. char classCount[sizeof(g_iRocketClassCount)];
  2057. IntToString(g_iRocketClassCount + 1, classCount, sizeof(classCount));
  2058. menu.AddItem(classCount, nochange);
  2059.  
  2060. menu.ExitButton = false;
  2061. menu.DisplayVoteToAll(20);
  2062.  
  2063. LogMessage("[VRC] Voting for rocket class has successfully started.");
  2064. }
  2065.  
  2066. public int Handler_RocketClassVoteMenu(Menu menu, MenuAction action, int param1, int param2)
  2067. {
  2068. switch (action)
  2069. {
  2070. case MenuAction_End:
  2071. {
  2072. delete menu;
  2073. }
  2074. case MenuAction_Select:
  2075. {
  2076. char voter[64], choice[64];
  2077. GetClientName(param1, voter, sizeof(voter));
  2078. menu.GetItem(param2, choice, sizeof(choice));
  2079. LogMessage("[VRC] %s Selected Rocket Class %s", voter, choice);
  2080. }
  2081. case MenuAction_VoteEnd:
  2082. {
  2083. char classNum[64];
  2084. char className[64];
  2085. int votes, totalVotes;
  2086. GetMenuVoteInfo(param2, votes, totalVotes);
  2087.  
  2088. if (totalVotes < 1)
  2089. {
  2090. CPrintToChatAll("%s %sVoting ended with %sno Votes!", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor);
  2091. return;
  2092. }
  2093.  
  2094. menu.GetItem(param1, classNum, sizeof(classNum));
  2095.  
  2096. strcopy(className, sizeof(className), g_strRocketClassLongName[param1]);
  2097.  
  2098. if (StrContains(className, "[Current]") != -1 || StringToInt(classNum) == (g_iRocketClassCount + 1))
  2099. {
  2100. CPrintToChatAll("%s %sCurrent Rocket Class %sStays", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor);
  2101. LogMessage("[VRC] Voting for Rocket Class has ended, current class kept.");
  2102. }
  2103. else
  2104. {
  2105. LogMessage("[VRC] Voting for Rocket Class has ended, changing class to %s.", className);
  2106. SetMainRocketClass(param1, true);
  2107. }
  2108. }
  2109. }
  2110. }
  2111.  
  2112. public Action Timer_AllowRocketClassVote(Handle timer, Handle hndl) {
  2113. g_bCanVoteClass = true;
  2114. }
  2115.  
  2116. // ___ _ _
  2117. // | _ \___ __| |_____| |_ ___
  2118. // | / _ \/ _| / / -_) _(_-<
  2119. // |_|_\___/\__|_\_\___|\__/__/
  2120.  
  2121. /* CreateRocket()
  2122. **
  2123. ** Fires a new rocket entity from the spawner's position.
  2124. ** -------------------------------------------------------------------------- */
  2125. public void CreateRocket(int iSpawnerEntity, int iSpawnerClass, int iTeam)
  2126. {
  2127. int iIndex = FindFreeRocketSlot();
  2128. if (iIndex != -1)
  2129. {
  2130. // Fetch a random rocket class and it's parameters.
  2131. int iClass = GetRandomRocketClass(iSpawnerClass);
  2132. RocketFlags iFlags = g_iRocketClassFlags[iClass];
  2133.  
  2134. // Create rocket entity.
  2135. int iEntity = CreateEntityByName(TestFlags(iFlags, RocketFlag_IsAnimated) ? "tf_projectile_sentryrocket" : "tf_projectile_rocket");
  2136. if (iEntity && IsValidEntity(iEntity))
  2137. {
  2138. // Fetch spawn point's location and angles.
  2139. float fPosition[3];
  2140. float fAngles[3];
  2141. float fDirection[3];
  2142. GetEntPropVector(iSpawnerEntity, Prop_Send, "m_vecOrigin", fPosition);
  2143. GetEntPropVector(iSpawnerEntity, Prop_Send, "m_angRotation", fAngles);
  2144. GetAngleVectors(fAngles, fDirection, NULL_VECTOR, NULL_VECTOR);
  2145.  
  2146. // Setup rocket entity.
  2147. SetEntPropEnt(iEntity, Prop_Send, "m_hOwnerEntity", 0);
  2148. SetEntProp(iEntity, Prop_Send, "m_bCritical", (GetURandomFloatRange(0.0, 100.0) <= g_fRocketClassCritChance[iClass]) ? 1 : 0, 1);
  2149. SetEntProp(iEntity, Prop_Send, "m_iTeamNum", iTeam, 1);
  2150. SetEntProp(iEntity, Prop_Send, "m_iDeflected", 1);
  2151. TeleportEntity(iEntity, fPosition, fAngles, view_as<float>( { 0.0, 0.0, 0.0 } ));
  2152.  
  2153. // Setup rocket structure with the newly created entity.
  2154. int iTargetTeam = (TestFlags(iFlags, RocketFlag_IsNeutral)) ? 0 : GetAnalogueTeam(iTeam);
  2155. int iTarget = SelectTarget(iTargetTeam);
  2156. float fModifier = CalculateModifier(iClass, 0);
  2157. g_bRocketIsValid[iIndex] = true;
  2158. g_iRocketFlags[iIndex] = iFlags;
  2159. g_iRocketEntity[iIndex] = EntIndexToEntRef(iEntity);
  2160. g_iRocketTarget[iIndex] = EntIndexToEntRef(iTarget);
  2161. g_iRocketSpawner[iIndex] = iSpawnerClass;
  2162. g_iRocketClass[iIndex] = iClass;
  2163. g_iRocketDeflections[iIndex] = 0;
  2164. g_fRocketLastDeflectionTime[iIndex] = GetGameTime();
  2165. g_fRocketLastBeepTime[iIndex] = GetGameTime();
  2166. g_fRocketSpeed[iIndex] = CalculateRocketSpeed(iClass, fModifier);
  2167. g_iRocketSpeed = RoundFloat(g_fRocketSpeed[iIndex] * 0.042614);
  2168.  
  2169. CopyVectors(fDirection, g_fRocketDirection[iIndex]);
  2170. SetEntDataFloat(iEntity, FindSendPropInfo("CTFProjectile_Rocket", "m_iDeflected") + 4, CalculateRocketDamage(iClass, fModifier), true);
  2171. DispatchSpawn(iEntity);
  2172.  
  2173. // Apply custom model, if specified on the flags.
  2174. if (TestFlags(iFlags, RocketFlag_CustomModel))
  2175. {
  2176. SetEntityModel(iEntity, g_strRocketClassModel[iClass]);
  2177. UpdateRocketSkin(iEntity, iTeam, TestFlags(iFlags, RocketFlag_IsNeutral));
  2178. }
  2179.  
  2180. // Execute commands on spawn.
  2181. if (TestFlags(iFlags, RocketFlag_OnSpawnCmd))
  2182. {
  2183. ExecuteCommands(g_hRocketClassCmdsOnSpawn[iClass], iClass, iEntity, 0, iTarget, g_iLastDeadClient, g_fRocketSpeed[iIndex], 0);
  2184. }
  2185.  
  2186. // Emit required sounds.
  2187. EmitRocketSound(RocketSound_Spawn, iClass, iEntity, iTarget, iFlags);
  2188. EmitRocketSound(RocketSound_Alert, iClass, iEntity, iTarget, iFlags);
  2189.  
  2190. // Done
  2191. g_iRocketCount++;
  2192. g_iRocketsFired++;
  2193. g_fLastSpawnTime = GetGameTime();
  2194. g_fNextSpawnTime = GetGameTime() + g_fSpawnersInterval[iSpawnerClass];
  2195. g_bRocketIsNuke[iIndex] = false;
  2196.  
  2197. //AttachParticle(iEntity, "burningplayer_rainbow_glow");
  2198. //AttachParticle(iEntity, "burningplayer_rainbow_glow_old");
  2199. //CreateTempParticle("superrare_greenenergy", iEntity, _, _, true);
  2200. //SDKHook(iEntity, SDKHook_SetTransmit, ShowToTarget);
  2201.  
  2202. //Observer
  2203. if (IsValidEntity(g_observer))
  2204. {
  2205. g_op_rocket = iEntity;
  2206. TeleportEntity(g_observer, fPosition, fAngles, view_as<float>( { 0.0, 0.0, 0.0 } ));
  2207. SetVariantString("!activator");
  2208. AcceptEntityInput(g_observer, "SetParent", g_op_rocket);
  2209. }
  2210. }
  2211. }
  2212. }
  2213.  
  2214. public void OnEntityDestroyed(int entity)
  2215. {
  2216. if (entity == -1)
  2217. {
  2218. return;
  2219. }
  2220.  
  2221. if (entity == g_op_rocket && g_bEnabled == true && IsValidEntity(g_observer) && IsValidEntity(g_op_rocket))
  2222. {
  2223. SetVariantString("");
  2224. AcceptEntityInput(g_observer, "ClearParent");
  2225. g_op_rocket = -1;
  2226.  
  2227. float opPos[3];
  2228. float opAng[3];
  2229.  
  2230. int spawner = GetRandomInt(0, 1);
  2231. if (spawner == 0)
  2232. spawner = g_iSpawnPointsRedEntity[0];
  2233. else
  2234. spawner = g_iSpawnPointsBluEntity[0];
  2235.  
  2236. if (IsValidEntity(spawner) && spawner > MAXPLAYERS)
  2237. {
  2238. GetEntPropVector(spawner, Prop_Data, "m_vecOrigin", opPos);
  2239. GetEntPropVector(spawner, Prop_Data, "m_angAbsRotation", opAng);
  2240. TeleportEntity(g_observer, opPos, opAng, NULL_VECTOR);
  2241. }
  2242. }
  2243. }
  2244.  
  2245.  
  2246. /* DestroyRocket()
  2247. **
  2248. ** Destroys the rocket at the given index.
  2249. ** -------------------------------------------------------------------------- */
  2250. void DestroyRocket(int iIndex)
  2251. {
  2252. if (IsValidRocket(iIndex) == true)
  2253. {
  2254. int iEntity = EntRefToEntIndex(g_iRocketEntity[iIndex]);
  2255. if (iEntity && IsValidEntity(iEntity))RemoveEdict(iEntity);
  2256. g_bRocketIsValid[iIndex] = false;
  2257. g_iRocketCount--;
  2258. }
  2259. }
  2260.  
  2261. /* DestroyRockets()
  2262. **
  2263. ** Destroys all the rockets that are currently active.
  2264. ** -------------------------------------------------------------------------- */
  2265. void DestroyRockets()
  2266. {
  2267. for (int iIndex = 0; iIndex < MAX_ROCKETS; iIndex++)
  2268. {
  2269. DestroyRocket(iIndex);
  2270. }
  2271. g_iRocketCount = 0;
  2272. }
  2273.  
  2274. /* IsValidRocket()
  2275. **
  2276. ** Checks if a rocket structure is valid.
  2277. ** -------------------------------------------------------------------------- */
  2278. bool IsValidRocket(int iIndex)
  2279. {
  2280. if ((iIndex >= 0) && (g_bRocketIsValid[iIndex] == true))
  2281. {
  2282. if (EntRefToEntIndex(g_iRocketEntity[iIndex]) == -1)
  2283. {
  2284. g_bRocketIsValid[iIndex] = false;
  2285. g_iRocketCount--;
  2286. return false;
  2287. }
  2288. return true;
  2289. }
  2290. return false;
  2291. }
  2292.  
  2293. /* FindNextValidRocket()
  2294. **
  2295. ** Retrieves the index of the next valid rocket from the current offset.
  2296. ** -------------------------------------------------------------------------- */
  2297. int FindNextValidRocket(int iIndex, bool bWrap = false)
  2298. {
  2299. for (int iCurrent = iIndex + 1; iCurrent < MAX_ROCKETS; iCurrent++)
  2300. if (IsValidRocket(iCurrent))
  2301. return iCurrent;
  2302.  
  2303. return (bWrap == true) ? FindNextValidRocket(-1, false) : -1;
  2304. }
  2305.  
  2306. /* FindFreeRocketSlot()
  2307. **
  2308. ** Retrieves the next free rocket slot since the current one. If all of them
  2309. ** are full, returns -1.
  2310. ** -------------------------------------------------------------------------- */
  2311. int FindFreeRocketSlot()
  2312. {
  2313. int iIndex = g_iLastCreatedRocket;
  2314. int iCurrent = iIndex;
  2315.  
  2316. do
  2317. {
  2318. if (!IsValidRocket(iCurrent))return iCurrent;
  2319. if ((++iCurrent) == MAX_ROCKETS)iCurrent = 0;
  2320. } while (iCurrent != iIndex);
  2321.  
  2322. return -1;
  2323. }
  2324.  
  2325. /* FindRocketByEntity()
  2326. **
  2327. ** Finds a rocket index from it's entity.
  2328. ** -------------------------------------------------------------------------- */
  2329. int FindRocketByEntity(int iEntity)
  2330. {
  2331. int iIndex = -1;
  2332. while ((iIndex = FindNextValidRocket(iIndex)) != -1)
  2333. if (EntRefToEntIndex(g_iRocketEntity[iIndex]) == iEntity)
  2334. return iIndex;
  2335.  
  2336. return -1;
  2337. }
  2338.  
  2339. /* HomingRocketThinkg()
  2340. **
  2341. ** Logic process for the Behaviour_Homing type rockets, wich is simply a
  2342. ** follower rocket, picking a random target.
  2343. ** -------------------------------------------------------------------------- */
  2344. void HomingRocketThink(int iIndex)
  2345. {
  2346. // Retrieve the rocket's attributes.
  2347. int iEntity = EntRefToEntIndex(g_iRocketEntity[iIndex]);
  2348. int iClass = g_iRocketClass[iIndex];
  2349. RocketFlags iFlags = g_iRocketFlags[iIndex];
  2350. int iTarget = EntRefToEntIndex(g_iRocketTarget[iIndex]);
  2351. int iTeam = GetEntProp(iEntity, Prop_Send, "m_iTeamNum", 1);
  2352. int iTargetTeam = (TestFlags(iFlags, RocketFlag_IsNeutral)) ? 0 : GetAnalogueTeam(iTeam);
  2353. int iDeflectionCount = GetEntProp(iEntity, Prop_Send, "m_iDeflected") - 1;
  2354. float fModifier = CalculateModifier(iClass, iDeflectionCount);
  2355. g_hRocketSpeed = RoundFloat(g_fRocketSpeed[iIndex]);
  2356. xDeflections = g_iRocketDeflections[iIndex];
  2357.  
  2358. // Check if the target is available
  2359. if (!IsValidClient(iTarget, true))
  2360. {
  2361. iTarget = SelectTarget(iTargetTeam);
  2362. if (!IsValidClient(iTarget, true))return;
  2363. g_iRocketTarget[iIndex] = EntIndexToEntRef(iTarget);
  2364.  
  2365. if (GetConVarBool(g_hCvarRedirectBeep))
  2366. {
  2367. EmitRocketSound(RocketSound_Alert, iClass, iEntity, iTarget, iFlags);
  2368. }
  2369. }
  2370. // Has the rocket been deflected recently? If so, set new target.
  2371. else if ((iDeflectionCount > g_iRocketDeflections[iIndex]))
  2372. {
  2373. // Calculate new direction from the player's forward
  2374. int iClient = GetEntPropEnt(iEntity, Prop_Send, "m_hOwnerEntity");
  2375. if (IsValidClient(iClient))
  2376. {
  2377. float fViewAngles[3];
  2378. float fDirection[3];
  2379. GetClientEyeAngles(iClient, fViewAngles);
  2380. GetAngleVectors(fViewAngles, fDirection, NULL_VECTOR, NULL_VECTOR);
  2381. CopyVectors(fDirection, g_fRocketDirection[iIndex]);
  2382. UpdateRocketSkin(iEntity, iTeam, TestFlags(iFlags, RocketFlag_IsNeutral));
  2383. if (GetConVarBool(g_hCvarStealPrevention))
  2384. {
  2385. checkStolenRocket(iClient, iIndex);
  2386. }
  2387. }
  2388.  
  2389. gDeflector = iClient;
  2390.  
  2391. // Set new target & deflection count
  2392. iTarget = SelectTarget(iTargetTeam, iIndex);
  2393. g_iRocketTarget[iIndex] = EntIndexToEntRef(iTarget);
  2394. g_iRocketDeflections[iIndex] = iDeflectionCount;
  2395. g_fRocketLastDeflectionTime[iIndex] = GetGameTime();
  2396. g_fRocketSpeed[iIndex] = CalculateRocketSpeed(iClass, fModifier);
  2397. g_iRocketSpeed = RoundFloat(g_fRocketSpeed[iIndex] * 0.042614);
  2398. g_bPreventingDelay = false;
  2399.  
  2400. SetEntDataFloat(iEntity, FindSendPropInfo("CTFProjectile_Rocket", "m_iDeflected") + 4, CalculateRocketDamage(iClass, fModifier), true);
  2401. if (TestFlags(iFlags, RocketFlag_ElevateOnDeflect))g_iRocketFlags[iIndex] |= RocketFlag_Elevating;
  2402. EmitRocketSound(RocketSound_Alert, iClass, iEntity, iTarget, iFlags);
  2403. //Send out temp entity to target
  2404. //SendTempEnt(iTarget, "superrare_greenenergy", iEntity, _, _, true);
  2405.  
  2406. // Execute appropiate command
  2407. if (TestFlags(iFlags, RocketFlag_OnDeflectCmd))
  2408. {
  2409. ExecuteCommands(g_hRocketClassCmdsOnDeflect[iClass], iClass, iEntity, iClient, iTarget, g_iLastDeadClient, g_fRocketSpeed[iIndex], iDeflectionCount);
  2410. }
  2411. }
  2412. else
  2413. {
  2414. // If the delay time since the last reflection has been elapsed, rotate towards the client.
  2415. if ((GetGameTime() - g_fRocketLastDeflectionTime[iIndex]) >= g_fRocketClassControlDelay[iClass])
  2416. {
  2417. // Calculate turn rate and retrieve directions.
  2418. float fTurnRate = CalculateRocketTurnRate(iClass, fModifier);
  2419. float fDirectionToTarget[3]; CalculateDirectionToClient(iEntity, iTarget, fDirectionToTarget);
  2420.  
  2421. // Elevate the rocket after a deflection (if it's enabled on the class definition, of course.)
  2422. if (g_iRocketFlags[iIndex] & RocketFlag_Elevating)
  2423. {
  2424. if (g_fRocketDirection[iIndex][2] < g_fRocketClassElevationLimit[iClass])
  2425. {
  2426. g_fRocketDirection[iIndex][2] = FMin(g_fRocketDirection[iIndex][2] + g_fRocketClassElevationRate[iClass], g_fRocketClassElevationLimit[iClass]);
  2427. fDirectionToTarget[2] = g_fRocketDirection[iIndex][2];
  2428. }
  2429. else
  2430. {
  2431. g_iRocketFlags[iIndex] &= ~RocketFlag_Elevating;
  2432. }
  2433. }
  2434.  
  2435. // Smoothly change the orientation to the new one.
  2436. LerpVectors(g_fRocketDirection[iIndex], fDirectionToTarget, g_fRocketDirection[iIndex], fTurnRate);
  2437. }
  2438.  
  2439. // If it's a nuke, beep every some time
  2440. if ((GetGameTime() - g_fRocketLastBeepTime[iIndex]) >= g_fRocketClassBeepInterval[iClass])
  2441. {
  2442. g_bRocketIsNuke[iIndex] = true;
  2443. EmitRocketSound(RocketSound_Beep, iClass, iEntity, iTarget, iFlags);
  2444. g_fRocketLastBeepTime[iIndex] = GetGameTime();
  2445. }
  2446.  
  2447. if (GetConVarBool(g_hCvarDelayPrevention))
  2448. {
  2449. checkRoundDelays(iIndex);
  2450. }
  2451. }
  2452.  
  2453. // Done
  2454. ApplyRocketParameters(iIndex);
  2455. }
  2456.  
  2457. public Action SetBack(Handle timer) {
  2458. IsOnTouch = false;
  2459. IsOnGameFrame = true;
  2460. }
  2461.  
  2462. /* CalculateModifier()
  2463. **
  2464. ** Gets the modifier for the damage/speed/rotation calculations.
  2465. ** -------------------------------------------------------------------------- */
  2466. float CalculateModifier(int iClass, int iDeflections)
  2467. {
  2468. return iDeflections +
  2469. (g_iRocketsFired * g_fRocketClassRocketsModifier[iClass]) +
  2470. (g_iPlayerCount * g_fRocketClassPlayerModifier[iClass]);
  2471. }
  2472.  
  2473. /* CalculateRocketDamage()
  2474. **
  2475. ** Calculates the damage of the rocket based on it's type and deflection count.
  2476. ** -------------------------------------------------------------------------- */
  2477. float CalculateRocketDamage(int iClass, float fModifier)
  2478. {
  2479. return g_fRocketClassDamage[iClass] + g_fRocketClassDamageIncrement[iClass] * fModifier;
  2480. }
  2481.  
  2482. /* CalculateRocketSpeed()
  2483. **
  2484. ** Calculates the speed of the rocket based on it's type and deflection count.
  2485. ** -------------------------------------------------------------------------- */
  2486. float CalculateRocketSpeed(int iClass, float fModifier)
  2487. {
  2488. return g_fRocketClassSpeed[iClass] + g_fRocketClassSpeedIncrement[iClass] * fModifier;
  2489. }
  2490.  
  2491. /* CalculateRocketTurnRate()
  2492. **
  2493. ** Calculates the rocket's turn rate based upon it's type and deflection count.
  2494. ** -------------------------------------------------------------------------- */
  2495. float CalculateRocketTurnRate(int iClass, float fModifier)
  2496. {
  2497. return g_fRocketClassTurnRate[iClass] + g_fRocketClassTurnRateIncrement[iClass] * fModifier;
  2498. }
  2499.  
  2500. /* CalculateDirectionToClient()
  2501. **
  2502. ** As the name indicates, calculates the orientation for the rocket to move
  2503. ** towards the specified client.
  2504. ** -------------------------------------------------------------------------- */
  2505. void CalculateDirectionToClient(int iEntity, int iClient, float fOut[3])
  2506. {
  2507. float fRocketPosition[3]; GetEntPropVector(iEntity, Prop_Send, "m_vecOrigin", fRocketPosition);
  2508. GetClientEyePosition(iClient, fOut);
  2509. MakeVectorFromPoints(fRocketPosition, fOut, fOut);
  2510. NormalizeVector(fOut, fOut);
  2511. }
  2512.  
  2513. /* ApplyRocketParameters()
  2514. **
  2515. ** Transforms and applies the speed, direction and angles for the rocket
  2516. ** entity.
  2517. ** -------------------------------------------------------------------------- */
  2518. void ApplyRocketParameters(int iIndex)
  2519. {
  2520. int iEntity = EntRefToEntIndex(g_iRocketEntity[iIndex]);
  2521. float fAngles[3]; GetVectorAngles(g_fRocketDirection[iIndex], fAngles);
  2522. float fVelocity[3]; CopyVectors(g_fRocketDirection[iIndex], fVelocity);
  2523. ScaleVector(fVelocity, g_fRocketSpeed[iIndex]);
  2524. SetEntPropVector(iEntity, Prop_Data, "m_vecAbsVelocity", fVelocity);
  2525. SetEntPropVector(iEntity, Prop_Send, "m_angRotation", fAngles);
  2526. }
  2527.  
  2528. /* UpdateRocketSkin()
  2529. **
  2530. ** Changes the skin of the rocket based on it's team.
  2531. ** -------------------------------------------------------------------------- */
  2532. void UpdateRocketSkin(int iEntity, int iTeam, bool bNeutral)
  2533. {
  2534. if (bNeutral == true)SetEntProp(iEntity, Prop_Send, "m_nSkin", 2);
  2535. else SetEntProp(iEntity, Prop_Send, "m_nSkin", (iTeam == view_as<int>(TFTeam_Blue)) ? 0 : 1);
  2536. }
  2537.  
  2538. /* GetRandomRocketClass()
  2539. **
  2540. ** Generates a random value and retrieves a rocket class based upon a chances table.
  2541. ** -------------------------------------------------------------------------- */
  2542. int GetRandomRocketClass(int iSpawnerClass)
  2543. {
  2544. int iRandom = GetURandomIntRange(0, 101);
  2545. Handle hTable = g_hSpawnersChancesTable[iSpawnerClass];
  2546. int iTableSize = GetArraySize(hTable);
  2547. int iChancesLower = 0;
  2548. int iChancesUpper = 0;
  2549.  
  2550. for (int iEntry = 0; iEntry < iTableSize; iEntry++)
  2551. {
  2552. iChancesLower += iChancesUpper;
  2553. iChancesUpper = iChancesLower + GetArrayCell(hTable, iEntry);
  2554.  
  2555. if ((iRandom >= iChancesLower) && (iRandom < iChancesUpper))
  2556. {
  2557. return iEntry;
  2558. }
  2559. }
  2560.  
  2561. return 0;
  2562. }
  2563.  
  2564. /* EmitRocketSound()
  2565. **
  2566. ** Emits one of the rocket sounds
  2567. ** -------------------------------------------------------------------------- */
  2568. void EmitRocketSound(RocketSound iSound, int iClass, int iEntity, int iTarget, RocketFlags iFlags)
  2569. {
  2570. switch (iSound)
  2571. {
  2572. case RocketSound_Spawn:
  2573. {
  2574. if (TestFlags(iFlags, RocketFlag_PlaySpawnSound))
  2575. {
  2576. if (TestFlags(iFlags, RocketFlag_CustomSpawnSound))EmitSoundToAll(g_strRocketClassSpawnSound[iClass], iEntity);
  2577. else EmitSoundToAll(SOUND_DEFAULT_SPAWN, iEntity);
  2578. }
  2579. }
  2580. case RocketSound_Beep:
  2581. {
  2582. if (TestFlags(iFlags, RocketFlag_PlayBeepSound))
  2583. {
  2584. if (TestFlags(iFlags, RocketFlag_CustomBeepSound))EmitSoundToAll(g_strRocketClassBeepSound[iClass], iEntity);
  2585. else EmitSoundToAll(SOUND_DEFAULT_BEEP, iEntity);
  2586. }
  2587. }
  2588. case RocketSound_Alert:
  2589. {
  2590. if (TestFlags(iFlags, RocketFlag_PlayAlertSound))
  2591. {
  2592. if (TestFlags(iFlags, RocketFlag_CustomAlertSound))EmitSoundToClient(iTarget, g_strRocketClassAlertSound[iClass]);
  2593. else EmitSoundToClient(iTarget, SOUND_DEFAULT_ALERT, _, _, _, _, 0.5);
  2594. }
  2595. }
  2596. }
  2597. }
  2598.  
  2599. // ___ _ _ ___ _
  2600. // | _ \___ __| |_____| |_ / __| |__ _ ______ ___ ___
  2601. // | / _ \/ _| / / -_) _| | (__| / _` (_-<_-</ -_|_-<
  2602. // |_|_\___/\__|_\_\___|\__| \___|_\__,_/__/__/\___/__/
  2603. //
  2604.  
  2605. /* DestroyRocketClasses()
  2606. **
  2607. ** Frees up all the rocket classes defined now.
  2608. ** -------------------------------------------------------------------------- */
  2609. void DestroyRocketClasses()
  2610. {
  2611. for (int iIndex = 0; iIndex < g_iRocketClassCount; iIndex++)
  2612. {
  2613. Handle hCmdOnSpawn = g_hRocketClassCmdsOnSpawn[iIndex];
  2614. Handle hCmdOnKill = g_hRocketClassCmdsOnKill[iIndex];
  2615. Handle hCmdOnExplode = g_hRocketClassCmdsOnExplode[iIndex];
  2616. Handle hCmdOnDeflect = g_hRocketClassCmdsOnDeflect[iIndex];
  2617. if (hCmdOnSpawn != INVALID_HANDLE)CloseHandle(hCmdOnSpawn);
  2618. if (hCmdOnKill != INVALID_HANDLE)CloseHandle(hCmdOnKill);
  2619. if (hCmdOnExplode != INVALID_HANDLE)CloseHandle(hCmdOnExplode);
  2620. if (hCmdOnDeflect != INVALID_HANDLE)CloseHandle(hCmdOnDeflect);
  2621. g_hRocketClassCmdsOnSpawn[iIndex] = INVALID_HANDLE;
  2622. g_hRocketClassCmdsOnKill[iIndex] = INVALID_HANDLE;
  2623. g_hRocketClassCmdsOnExplode[iIndex] = INVALID_HANDLE;
  2624. g_hRocketClassCmdsOnDeflect[iIndex] = INVALID_HANDLE;
  2625. }
  2626. g_iRocketClassCount = 0;
  2627. ClearTrie(g_hRocketClassTrie);
  2628. }
  2629.  
  2630. // ___ ___ _ _ _ ___ _
  2631. // / __|_ __ __ ___ __ ___ _ | _ \___(_)_ _| |_ ___ __ _ _ _ __| | / __| |__ _ ______ ___ ___
  2632. // \__ \ '_ \/ _` \ V V / ' \ | _/ _ \ | ' \ _(_-< / _` | ' \/ _` | | (__| / _` (_-<_-</ -_|_-<
  2633. // |___/ .__/\__,_|\_/\_/|_||_| |_| \___/_|_||_\__/__/ \__,_|_||_\__,_| \___|_\__,_/__/__/\___/__/
  2634. // |_|
  2635.  
  2636. /* DestroySpawners()
  2637. **
  2638. ** Frees up all the spawner points defined up to now.
  2639. ** -------------------------------------------------------------------------- */
  2640. void DestroySpawners()
  2641. {
  2642. for (int iIndex = 0; iIndex < g_iSpawnersCount; iIndex++)
  2643. {
  2644. CloseHandle(g_hSpawnersChancesTable[iIndex]);
  2645. }
  2646. g_iSpawnersCount = 0;
  2647. g_iSpawnPointsRedCount = 0;
  2648. g_iSpawnPointsBluCount = 0;
  2649. g_iDefaultRedSpawner = -1;
  2650. g_iDefaultBluSpawner = -1;
  2651. g_strSavedClassName[0] = '\0';
  2652. ClearTrie(g_hSpawnersTrie);
  2653. }
  2654.  
  2655. /* PopulateSpawnPoints()
  2656. **
  2657. ** Iterates through all the possible spawn points and assigns them an spawner.
  2658. ** -------------------------------------------------------------------------- */
  2659. void PopulateSpawnPoints()
  2660. {
  2661. // Clear the current settings
  2662. g_iSpawnPointsRedCount = 0;
  2663. g_iSpawnPointsBluCount = 0;
  2664.  
  2665. // Iterate through all the info target points and check 'em out.
  2666. int iEntity = -1;
  2667. while ((iEntity = FindEntityByClassname(iEntity, "info_target")) != -1)
  2668. {
  2669. char strName[32]; GetEntPropString(iEntity, Prop_Data, "m_iName", strName, sizeof(strName));
  2670. if ((StrContains(strName, "rocket_spawn_red") != -1) || (StrContains(strName, "tf_dodgeball_red") != -1))
  2671. {
  2672. // Find most appropiate spawner class for this entity.
  2673. int iIndex = FindSpawnerByName(strName);
  2674. if (!IsValidRocket(iIndex)) iIndex = g_iDefaultRedSpawner;
  2675.  
  2676. // Upload to point list
  2677. g_iSpawnPointsRedClass[g_iSpawnPointsRedCount] = iIndex;
  2678. g_iSpawnPointsRedEntity[g_iSpawnPointsRedCount] = iEntity;
  2679. g_iSpawnPointsRedCount++;
  2680. }
  2681. if ((StrContains(strName, "rocket_spawn_blue") != -1) || (StrContains(strName, "tf_dodgeball_blu") != -1))
  2682. {
  2683. // Find most appropiate spawner class for this entity.
  2684. int iIndex = FindSpawnerByName(strName);
  2685. if (!IsValidRocket(iIndex))iIndex = g_iDefaultBluSpawner;
  2686.  
  2687. // Upload to point list
  2688. g_iSpawnPointsBluClass[g_iSpawnPointsBluCount] = iIndex;
  2689. g_iSpawnPointsBluEntity[g_iSpawnPointsBluCount] = iEntity;
  2690. g_iSpawnPointsBluCount++;
  2691. }
  2692. }
  2693.  
  2694. // Check if there exists spawn points
  2695. if (g_iSpawnPointsRedCount == 0)
  2696. SetFailState("No RED spawn points found on this map.");
  2697.  
  2698. if (g_iSpawnPointsBluCount == 0)
  2699. SetFailState("No BLU spawn points found on this map.");
  2700.  
  2701.  
  2702. //ObserverPoint
  2703. float opPos[3];
  2704. float opAng[3];
  2705.  
  2706. int spawner = GetRandomInt(0, 1);
  2707. if (spawner == 0)
  2708. spawner = g_iSpawnPointsRedEntity[0];
  2709. else
  2710. spawner = g_iSpawnPointsBluEntity[0];
  2711.  
  2712. if (IsValidEntity(spawner) && spawner > MAXPLAYERS)
  2713. {
  2714. GetEntPropVector(spawner, Prop_Data, "m_vecOrigin", opPos);
  2715. GetEntPropVector(spawner, Prop_Data, "m_angAbsRotation", opAng);
  2716. g_observer = CreateEntityByName("info_observer_point");
  2717. DispatchKeyValue(g_observer, "Angles", "90 0 0");
  2718. DispatchKeyValue(g_observer, "TeamNum", "0");
  2719. DispatchKeyValue(g_observer, "StartDisabled", "0");
  2720. DispatchSpawn(g_observer);
  2721. AcceptEntityInput(g_observer, "Enable");
  2722. TeleportEntity(g_observer, opPos, opAng, NULL_VECTOR);
  2723. }
  2724. else
  2725. {
  2726. g_observer = -1;
  2727. }
  2728.  
  2729. }
  2730.  
  2731. /* FindSpawnerByName()
  2732. **
  2733. ** Finds the first spawner wich contains the given name.
  2734. ** -------------------------------------------------------------------------- */
  2735. int FindSpawnerByName(char strName[32])
  2736. {
  2737. int iIndex = -1;
  2738. GetTrieValue(g_hSpawnersTrie, strName, iIndex);
  2739. return iIndex;
  2740. }
  2741.  
  2742.  
  2743. /*
  2744. **����������������������������������������������������������������������������������
  2745. ** ______ __
  2746. ** / ____/___ ____ ___ ____ ___ ____ _____ ____/ /____
  2747. ** / / / __ \/ __ `__ \/ __ `__ \/ __ `/ __ \/ __ / ___/
  2748. ** / /___/ /_/ / / / / / / / / / / / /_/ / / / / /_/ (__ )
  2749. ** \____/\____/_/ /_/ /_/_/ /_/ /_/\__,_/_/ /_/\__,_/____/
  2750. **
  2751. **����������������������������������������������������������������������������������
  2752. */
  2753.  
  2754. /* RegisterCommands()
  2755. **
  2756. ** Creates helper server commands to use with the plugin's events system.
  2757. ** -------------------------------------------------------------------------- */
  2758. void RegisterCommands()
  2759. {
  2760. RegServerCmd("tf_dodgeball_explosion", CmdExplosion);
  2761. RegServerCmd("tf_dodgeball_shockwave", CmdShockwave);
  2762. RegServerCmd("tf_dodgeball_resize", CmdResize);
  2763. }
  2764.  
  2765. public Action CmdResize(int iIndex)
  2766. {
  2767. int iEntity = EntRefToEntIndex(g_iRocketEntity[iIndex]);
  2768. if (iEntity && IsValidEntity(iEntity) && g_bRocketIsNuke[iEntity])
  2769. {
  2770. SetEntPropFloat(iEntity, Prop_Send, "m_flModelScale", (4.0));
  2771. }
  2772. }
  2773.  
  2774. /* CmdExplosion()
  2775. **
  2776. ** Creates a huge explosion at the location of the client.
  2777. ** -------------------------------------------------------------------------- */
  2778. public Action CmdExplosion(int iArgs)
  2779. {
  2780. if (iArgs == 1)
  2781. {
  2782. char strBuffer[8], iClient;
  2783. GetCmdArg(1, strBuffer, sizeof(strBuffer));
  2784. iClient = StringToInt(strBuffer);
  2785. if (IsValidEntity(iClient))
  2786. {
  2787. float fPosition[3];
  2788. GetClientAbsOrigin(iClient, fPosition);
  2789. switch (GetURandomIntRange(0, 4))
  2790. {
  2791. case 0:
  2792. {
  2793. PlayParticle(fPosition, PARTICLE_NUKE_1_ANGLES, PARTICLE_NUKE_1);
  2794. }
  2795. case 1:
  2796. {
  2797. PlayParticle(fPosition, PARTICLE_NUKE_2_ANGLES, PARTICLE_NUKE_2);
  2798. }
  2799. case 2:
  2800. {
  2801. PlayParticle(fPosition, PARTICLE_NUKE_3_ANGLES, PARTICLE_NUKE_3);
  2802. }
  2803. case 3:
  2804. {
  2805. PlayParticle(fPosition, PARTICLE_NUKE_4_ANGLES, PARTICLE_NUKE_4);
  2806. }
  2807. case 4:
  2808. {
  2809. PlayParticle(fPosition, PARTICLE_NUKE_5_ANGLES, PARTICLE_NUKE_5);
  2810. }
  2811. }
  2812. PlayParticle(fPosition, PARTICLE_NUKE_COLLUMN_ANGLES, PARTICLE_NUKE_COLLUMN);
  2813. }
  2814. }
  2815. else
  2816. {
  2817. PrintToServer("Usage: tf_dodgeball_explosion <client index>");
  2818. }
  2819.  
  2820. return Plugin_Handled;
  2821. }
  2822.  
  2823. /* CmdShockwave()
  2824. **
  2825. ** Creates a huge shockwave at the location of the client, with the given
  2826. ** parameters.
  2827. ** -------------------------------------------------------------------------- */
  2828. public Action CmdShockwave(int iArgs)
  2829. {
  2830. if (iArgs == 5)
  2831. {
  2832. char strBuffer[8];
  2833. int iClient;
  2834. int iTeam;
  2835. float fPosition[3];
  2836. int iDamage;
  2837. float fPushStrength;
  2838. float fRadius;
  2839. float fFalloffRadius;
  2840. GetCmdArg(1, strBuffer, sizeof(strBuffer)); iClient = StringToInt(strBuffer);
  2841. GetCmdArg(2, strBuffer, sizeof(strBuffer)); iDamage = StringToInt(strBuffer);
  2842. GetCmdArg(3, strBuffer, sizeof(strBuffer)); fPushStrength = StringToFloat(strBuffer);
  2843. GetCmdArg(4, strBuffer, sizeof(strBuffer)); fRadius = StringToFloat(strBuffer);
  2844. GetCmdArg(5, strBuffer, sizeof(strBuffer)); fFalloffRadius = StringToFloat(strBuffer);
  2845.  
  2846. if (IsValidClient(iClient))
  2847. {
  2848. iTeam = GetClientTeam(iClient);
  2849. GetClientAbsOrigin(iClient, fPosition);
  2850.  
  2851. for (iClient = 1; iClient <= MaxClients; iClient++)
  2852. {
  2853. if ((IsValidClient(iClient, true) == true) && (GetClientTeam(iClient) == iTeam))
  2854. {
  2855. float fPlayerPosition[3]; GetClientEyePosition(iClient, fPlayerPosition);
  2856. float fDistanceToShockwave = GetVectorDistance(fPosition, fPlayerPosition);
  2857.  
  2858. if (fDistanceToShockwave < fRadius)
  2859. {
  2860. float fImpulse[3];
  2861. float fFinalPush;
  2862. int iFinalDamage;
  2863. fImpulse[0] = fPlayerPosition[0] - fPosition[0];
  2864. fImpulse[1] = fPlayerPosition[1] - fPosition[1];
  2865. fImpulse[2] = fPlayerPosition[2] - fPosition[2];
  2866. NormalizeVector(fImpulse, fImpulse);
  2867. if (fImpulse[2] < 0.4) { fImpulse[2] = 0.4; NormalizeVector(fImpulse, fImpulse); }
  2868.  
  2869. if (fDistanceToShockwave < fFalloffRadius)
  2870. {
  2871. fFinalPush = fPushStrength;
  2872. iFinalDamage = iDamage;
  2873. }
  2874. else
  2875. {
  2876. float fImpact = (1.0 - ((fDistanceToShockwave - fFalloffRadius) / (fRadius - fFalloffRadius)));
  2877. fFinalPush = fImpact * fPushStrength;
  2878. iFinalDamage = RoundToFloor(fImpact * iDamage);
  2879. }
  2880. ScaleVector(fImpulse, fFinalPush);
  2881. SetEntPropVector(iClient, Prop_Data, "m_vecAbsVelocity", fImpulse);
  2882.  
  2883. Handle hDamage = CreateDataPack();
  2884. WritePackCell(hDamage, iClient);
  2885. WritePackCell(hDamage, iFinalDamage);
  2886. CreateTimer(0.1, ApplyDamage, hDamage, TIMER_FLAG_NO_MAPCHANGE);
  2887. }
  2888. }
  2889. }
  2890. }
  2891. }
  2892. else
  2893. {
  2894. PrintToServer("Usage: tf_dodgeball_shockwave <client index> <damage> <push strength> <radius> <falloff>");
  2895. }
  2896.  
  2897. return Plugin_Handled;
  2898. }
  2899.  
  2900. /* ExecuteCommands()
  2901. **
  2902. ** The core of the plugin's event system, unpacks and correctly formats the
  2903. ** given command strings to be executed.
  2904. ** -------------------------------------------------------------------------- */
  2905. void ExecuteCommands(Handle hDataPack, int iClass, int iRocket, int iOwner, int iTarget, int iLastDead, float fSpeed, int iNumDeflections)
  2906. {
  2907. ResetPack(hDataPack, false);
  2908. int iNumCommands = ReadPackCell(hDataPack);
  2909. while (iNumCommands-- > 0)
  2910. {
  2911. char strCmd[256];
  2912. char strBuffer[8];
  2913. ReadPackString(hDataPack, strCmd, sizeof(strCmd));
  2914. ReplaceString(strCmd, sizeof(strCmd), "@name", g_strRocketClassLongName[iClass]);
  2915. Format(strBuffer, sizeof(strBuffer), "%i", iRocket); ReplaceString(strCmd, sizeof(strCmd), "@rocket", strBuffer);
  2916. Format(strBuffer, sizeof(strBuffer), "%i", iOwner); ReplaceString(strCmd, sizeof(strCmd), "@owner", strBuffer);
  2917. Format(strBuffer, sizeof(strBuffer), "%i", iTarget); ReplaceString(strCmd, sizeof(strCmd), "@target", strBuffer);
  2918. Format(strBuffer, sizeof(strBuffer), "%i", iLastDead); ReplaceString(strCmd, sizeof(strCmd), "@dead", strBuffer);
  2919. Format(strBuffer, sizeof(strBuffer), "%f", fSpeed); ReplaceString(strCmd, sizeof(strCmd), "@speed", strBuffer);
  2920. Format(strBuffer, sizeof(strBuffer), "%i", iNumDeflections); ReplaceString(strCmd, sizeof(strCmd), "@deflections", strBuffer);
  2921. ServerCommand(strCmd);
  2922. }
  2923. }
  2924.  
  2925. /*
  2926. **����������������������������������������������������������������������������������
  2927. ** ______ _____
  2928. ** / ____/___ ____ / __(_)___ _
  2929. ** / / / __ \/ __ \/ /_/ / __ `/
  2930. ** / /___/ /_/ / / / / __/ / /_/ /
  2931. ** \____/\____/_/ /_/_/ /_/\__, /
  2932. ** /____/
  2933. **����������������������������������������������������������������������������������
  2934. */
  2935.  
  2936. /* ParseConfiguration()
  2937. **
  2938. ** Parses a Dodgeball configuration file. It doesn't clear any of the previous
  2939. ** data, so multiple files can be parsed.
  2940. ** -------------------------------------------------------------------------- */
  2941. bool ParseConfigurations(char strConfigFile[] = "general.cfg")
  2942. {
  2943. // Parse configuration
  2944. char strPath[PLATFORM_MAX_PATH];
  2945. char strFileName[PLATFORM_MAX_PATH];
  2946. Format(strFileName, sizeof(strFileName), "configs/dodgeball/%s", strConfigFile);
  2947. BuildPath(Path_SM, strPath, sizeof(strPath), strFileName);
  2948.  
  2949. // Try to parse if it exists
  2950. LogMessage("Executing configuration file %s", strPath);
  2951. if (FileExists(strPath, true))
  2952. {
  2953. KeyValues kvConfig = CreateKeyValues("TF2_Dodgeball");
  2954.  
  2955. if (FileToKeyValues(kvConfig, strPath) == false)
  2956. SetFailState("Error while parsing the configuration file.");
  2957.  
  2958. kvConfig.GotoFirstSubKey();
  2959.  
  2960. // Parse the subsections
  2961. do
  2962. {
  2963. char strSection[64];
  2964. KvGetSectionName(kvConfig, strSection, sizeof(strSection));
  2965.  
  2966. if (StrEqual(strSection, "general"))
  2967. ParseGeneral(kvConfig);
  2968. else if (StrEqual(strSection, "classes"))
  2969. ParseClasses(kvConfig);
  2970. else if (StrEqual(strSection, "spawners"))
  2971. ParseSpawners(kvConfig);
  2972. }
  2973. while (KvGotoNextKey(kvConfig));
  2974.  
  2975. CloseHandle(kvConfig);
  2976. }
  2977. }
  2978.  
  2979. /* ParseGeneral()
  2980. **
  2981. ** Parses general settings, such as the music, urls, etc.
  2982. ** -------------------------------------------------------------------------- */
  2983. void ParseGeneral(Handle kvConfig)
  2984. {
  2985. g_bMusicEnabled = view_as<bool>(KvGetNum(kvConfig, "music", 0));
  2986. if (g_bMusicEnabled == true)
  2987. {
  2988. g_bUseWebPlayer = view_as<bool>(KvGetNum(kvConfig, "use web player", 0));
  2989. KvGetString(kvConfig, "web player url", g_strWebPlayerUrl, sizeof(g_strWebPlayerUrl));
  2990.  
  2991. g_bMusic[Music_RoundStart] = KvGetString(kvConfig, "round start", g_strMusic[Music_RoundStart], PLATFORM_MAX_PATH) && strlen(g_strMusic[Music_RoundStart]);
  2992. g_bMusic[Music_RoundWin] = KvGetString(kvConfig, "round end (win)", g_strMusic[Music_RoundWin], PLATFORM_MAX_PATH) && strlen(g_strMusic[Music_RoundWin]);
  2993. g_bMusic[Music_RoundLose] = KvGetString(kvConfig, "round end (lose)", g_strMusic[Music_RoundLose], PLATFORM_MAX_PATH) && strlen(g_strMusic[Music_RoundLose]);
  2994. g_bMusic[Music_Gameplay] = KvGetString(kvConfig, "gameplay", g_strMusic[Music_Gameplay], PLATFORM_MAX_PATH) && strlen(g_strMusic[Music_Gameplay]);
  2995. }
  2996. }
  2997.  
  2998. /* ParseClasses()
  2999. **
  3000. ** Parses the rocket classes data from the given configuration file.
  3001. ** -------------------------------------------------------------------------- */
  3002. void ParseClasses(Handle kvConfig)
  3003. {
  3004. char strName[64];
  3005. char strBuffer[256];
  3006.  
  3007. KvGotoFirstSubKey(kvConfig);
  3008. do
  3009. {
  3010. int iIndex = g_iRocketClassCount;
  3011. RocketFlags iFlags;
  3012.  
  3013. // Basic parameters
  3014. KvGetSectionName(kvConfig, strName, sizeof(strName)); strcopy(g_strRocketClassName[iIndex], 16, strName);
  3015. KvGetString(kvConfig, "name", strBuffer, sizeof(strBuffer)); strcopy(g_strRocketClassLongName[iIndex], 32, strBuffer);
  3016. if (KvGetString(kvConfig, "model", strBuffer, sizeof(strBuffer)))
  3017. {
  3018. strcopy(g_strRocketClassModel[iIndex], PLATFORM_MAX_PATH, strBuffer);
  3019. if (strlen(g_strRocketClassModel[iIndex]) != 0)
  3020. {
  3021. iFlags |= RocketFlag_CustomModel;
  3022. if (KvGetNum(kvConfig, "is animated", 0))iFlags |= RocketFlag_IsAnimated;
  3023. }
  3024. }
  3025.  
  3026. KvGetString(kvConfig, "behaviour", strBuffer, sizeof(strBuffer), "homing");
  3027. if (StrEqual(strBuffer, "homing"))g_iRocketClassBehaviour[iIndex] = Behaviour_Homing;
  3028. else g_iRocketClassBehaviour[iIndex] = Behaviour_Unknown;
  3029.  
  3030. if (KvGetNum(kvConfig, "play spawn sound", 0) == 1)
  3031. {
  3032. iFlags |= RocketFlag_PlaySpawnSound;
  3033. if (KvGetString(kvConfig, "spawn sound", g_strRocketClassSpawnSound[iIndex], PLATFORM_MAX_PATH) && (strlen(g_strRocketClassSpawnSound[iIndex]) != 0))
  3034. {
  3035. iFlags |= RocketFlag_CustomSpawnSound;
  3036. }
  3037. }
  3038.  
  3039. if (KvGetNum(kvConfig, "play beep sound", 0) == 1)
  3040. {
  3041. iFlags |= RocketFlag_PlayBeepSound;
  3042. g_fRocketClassBeepInterval[iIndex] = KvGetFloat(kvConfig, "beep interval", 0.5);
  3043. if (KvGetString(kvConfig, "beep sound", g_strRocketClassBeepSound[iIndex], PLATFORM_MAX_PATH) && (strlen(g_strRocketClassBeepSound[iIndex]) != 0))
  3044. {
  3045. iFlags |= RocketFlag_CustomBeepSound;
  3046. }
  3047. }
  3048.  
  3049. if (KvGetNum(kvConfig, "play alert sound", 0) == 1)
  3050. {
  3051. iFlags |= RocketFlag_PlayAlertSound;
  3052. if (KvGetString(kvConfig, "alert sound", g_strRocketClassAlertSound[iIndex], PLATFORM_MAX_PATH) && strlen(g_strRocketClassAlertSound[iIndex]) != 0)
  3053. {
  3054. iFlags |= RocketFlag_CustomAlertSound;
  3055. }
  3056. }
  3057.  
  3058. // Behaviour modifiers
  3059. if (KvGetNum(kvConfig, "elevate on deflect", 1) == 1)iFlags |= RocketFlag_ElevateOnDeflect;
  3060. if (KvGetNum(kvConfig, "neutral rocket", 0) == 1)iFlags |= RocketFlag_IsNeutral;
  3061.  
  3062. // Movement parameters
  3063. g_fRocketClassDamage[iIndex] = KvGetFloat(kvConfig, "damage");
  3064. g_fRocketClassDamageIncrement[iIndex] = KvGetFloat(kvConfig, "damage increment");
  3065. g_fRocketClassCritChance[iIndex] = KvGetFloat(kvConfig, "critical chance");
  3066. g_fRocketClassSpeed[iIndex] = KvGetFloat(kvConfig, "speed");
  3067. g_fSavedSpeed = g_fRocketClassSpeed[iIndex];
  3068. g_fRocketClassSpeedIncrement[iIndex] = KvGetFloat(kvConfig, "speed increment");
  3069. g_fSavedSpeedIncrement = g_fRocketClassSpeedIncrement[iIndex];
  3070. g_fRocketClassTurnRate[iIndex] = KvGetFloat(kvConfig, "turn rate");
  3071. g_fRocketClassTurnRateIncrement[iIndex] = KvGetFloat(kvConfig, "turn rate increment");
  3072. g_fRocketClassElevationRate[iIndex] = KvGetFloat(kvConfig, "elevation rate");
  3073. g_fRocketClassElevationLimit[iIndex] = KvGetFloat(kvConfig, "elevation limit");
  3074. g_fRocketClassControlDelay[iIndex] = KvGetFloat(kvConfig, "control delay");
  3075. g_fRocketClassPlayerModifier[iIndex] = KvGetFloat(kvConfig, "no. players modifier");
  3076. g_fRocketClassRocketsModifier[iIndex] = KvGetFloat(kvConfig, "no. rockets modifier");
  3077. g_fRocketClassTargetWeight[iIndex] = KvGetFloat(kvConfig, "direction to target weight");
  3078.  
  3079. // Events
  3080. Handle hCmds = INVALID_HANDLE;
  3081. KvGetString(kvConfig, "on spawn", strBuffer, sizeof(strBuffer));
  3082. if ((hCmds = ParseCommands(strBuffer)) != INVALID_HANDLE) { iFlags |= RocketFlag_OnSpawnCmd; g_hRocketClassCmdsOnSpawn[iIndex] = hCmds; }
  3083. KvGetString(kvConfig, "on deflect", strBuffer, sizeof(strBuffer));
  3084. if ((hCmds = ParseCommands(strBuffer)) != INVALID_HANDLE) { iFlags |= RocketFlag_OnDeflectCmd; g_hRocketClassCmdsOnDeflect[iIndex] = hCmds; }
  3085. KvGetString(kvConfig, "on kill", strBuffer, sizeof(strBuffer));
  3086. if ((hCmds = ParseCommands(strBuffer)) != INVALID_HANDLE) { iFlags |= RocketFlag_OnKillCmd; g_hRocketClassCmdsOnKill[iIndex] = hCmds; }
  3087. KvGetString(kvConfig, "on explode", strBuffer, sizeof(strBuffer));
  3088. if ((hCmds = ParseCommands(strBuffer)) != INVALID_HANDLE) { iFlags |= RocketFlag_OnExplodeCmd; g_hRocketClassCmdsOnExplode[iIndex] = hCmds; }
  3089.  
  3090. // Done
  3091. SetTrieValue(g_hRocketClassTrie, strName, iIndex);
  3092. g_iRocketClassFlags[iIndex] = iFlags;
  3093. g_iRocketClassCount++;
  3094. }
  3095. while (KvGotoNextKey(kvConfig));
  3096. KvGoBack(kvConfig);
  3097. }
  3098.  
  3099. /* ParseSpawners()
  3100. **
  3101. ** Parses the spawn points classes data from the given configuration file.
  3102. ** -------------------------------------------------------------------------- */
  3103. void ParseSpawners(KeyValues kvConfig)
  3104. {
  3105. kvConfig.JumpToKey("spawners"); //jump to spawners section
  3106. char strBuffer[256];
  3107. kvConfig.GotoFirstSubKey(); //goto to first subkey of "spawners" section
  3108.  
  3109. do
  3110. {
  3111. int iIndex = g_iSpawnersCount;
  3112.  
  3113. // Basic parameters
  3114. kvConfig.GetSectionName(strBuffer, sizeof(strBuffer)); //okay, here we got section name, as example, red
  3115. strcopy(g_strSpawnersName[iIndex], 32, strBuffer); //here we copied it to the g_strSpawnersName array
  3116. g_iSpawnersMaxRockets[iIndex] = kvConfig.GetNum("max rockets", 1); //get some values...
  3117. g_fSpawnersInterval[iIndex] = kvConfig.GetFloat("interval", 1.0);
  3118.  
  3119. // Chances table
  3120. g_hSpawnersChancesTable[iIndex] = CreateArray(); //not interested in this
  3121. for (int iClassIndex = 0; iClassIndex < g_iRocketClassCount; iClassIndex++)
  3122. {
  3123. Format(strBuffer, sizeof(strBuffer), "%s%%", g_strRocketClassName[iClassIndex]);
  3124. PushArrayCell(g_hSpawnersChancesTable[iIndex], KvGetNum(kvConfig, strBuffer, 0));
  3125. if (KvGetNum(kvConfig, strBuffer, 0) == 100) strcopy(g_strSavedClassName, sizeof(g_strSavedClassName), g_strRocketClassLongName[iClassIndex]);
  3126. }
  3127.  
  3128. // Done.
  3129. SetTrieValue(g_hSpawnersTrie, g_strSpawnersName[iIndex], iIndex); //okay, push section name to g_hSpawnersTrie
  3130. g_iSpawnersCount++;
  3131. } while (kvConfig.GotoNextKey());
  3132.  
  3133. kvConfig.Rewind(); //rewind
  3134.  
  3135. GetTrieValue(g_hSpawnersTrie, "Red", g_iDefaultRedSpawner); //get value by section name, section name exists in the g_hSpawnersTrie, everything should work
  3136. GetTrieValue(g_hSpawnersTrie, "Blue", g_iDefaultBluSpawner);
  3137. }
  3138.  
  3139. /* ParseCommands()
  3140. **
  3141. ** Part of the event system, parses the given command strings and packs them
  3142. ** to a Datapack.
  3143. ** -------------------------------------------------------------------------- */
  3144. Handle ParseCommands(char[] strLine)
  3145. {
  3146. TrimString(strLine);
  3147. if (strlen(strLine) == 0)
  3148. {
  3149. return INVALID_HANDLE;
  3150. }
  3151. else
  3152. {
  3153. char strStrings[8][255];
  3154. int iNumStrings = ExplodeString(strLine, ";", strStrings, 8, 255);
  3155.  
  3156. Handle hDataPack = CreateDataPack();
  3157. WritePackCell(hDataPack, iNumStrings);
  3158. for (int i = 0; i < iNumStrings; i++)
  3159. {
  3160. WritePackString(hDataPack, strStrings[i]);
  3161. }
  3162.  
  3163. return hDataPack;
  3164. }
  3165. }
  3166.  
  3167. /*
  3168. **����������������������������������������������������������������������������������
  3169. ** ______ __
  3170. ** /_ __/___ ____ / /____
  3171. ** / / / __ \/ __ \/ / ___/
  3172. ** / / / /_/ / /_/ / (__ )
  3173. ** /_/ \____/\____/_/____/
  3174. **
  3175. **����������������������������������������������������������������������������������
  3176. */
  3177.  
  3178. /* ApplyDamage()
  3179. **
  3180. ** Applies a damage to a player.
  3181. ** -------------------------------------------------------------------------- */
  3182. public Action ApplyDamage(Handle hTimer, any hDataPack)
  3183. {
  3184. ResetPack(hDataPack, false);
  3185. int iClient = ReadPackCell(hDataPack);
  3186. int iDamage = ReadPackCell(hDataPack);
  3187. CloseHandle(hDataPack);
  3188. SlapPlayer(iClient, iDamage, true);
  3189. }
  3190.  
  3191. /* CopyVectors()
  3192. **
  3193. ** Copies the contents from a vector to another.
  3194. ** -------------------------------------------------------------------------- */
  3195. stock void CopyVectors(float fFrom[3], float fTo[3])
  3196. {
  3197. fTo[0] = fFrom[0];
  3198. fTo[1] = fFrom[1];
  3199. fTo[2] = fFrom[2];
  3200. }
  3201.  
  3202. /* LerpVectors()
  3203. **
  3204. ** Calculates the linear interpolation of the two given vectors and stores
  3205. ** it on the third one.
  3206. ** -------------------------------------------------------------------------- */
  3207. stock void LerpVectors(float fA[3], float fB[3], float fC[3], float t)
  3208. {
  3209. if (t < 0.0)t = 0.0;
  3210. if (t > 1.0)t = 1.0;
  3211.  
  3212. fC[0] = fA[0] + (fB[0] - fA[0]) * t;
  3213. fC[1] = fA[1] + (fB[1] - fA[1]) * t;
  3214. fC[2] = fA[2] + (fB[2] - fA[2]) * t;
  3215. }
  3216.  
  3217. /* IsValidClient()
  3218. **
  3219. ** Checks if the given client index is valid, and if it's alive or not.
  3220. ** -------------------------------------------------------------------------- */
  3221. stock bool IsValidClient(int iClient, bool bAlive = false)
  3222. {
  3223. if (iClient >= 1 &&
  3224. iClient <= MaxClients &&
  3225. IsClientConnected(iClient) &&
  3226. IsClientInGame(iClient) &&
  3227. (bAlive == false || IsPlayerAlive(iClient)))
  3228. {
  3229. return true;
  3230. }
  3231.  
  3232. return false;
  3233. }
  3234.  
  3235. /* BothTeamsPlaying()
  3236. **
  3237. ** Checks if there are players on both teams.
  3238. ** -------------------------------------------------------------------------- */
  3239. stock bool BothTeamsPlaying()
  3240. {
  3241. bool bRedFound;
  3242. bool bBluFound;
  3243. for (int iClient = 1; iClient <= MaxClients; iClient++)
  3244. {
  3245. if (IsValidClient(iClient, true) == false)continue;
  3246. int iTeam = GetClientTeam(iClient);
  3247. if (iTeam == view_as<int>(TFTeam_Red))bRedFound = true;
  3248. if (iTeam == view_as<int>(TFTeam_Blue))bBluFound = true;
  3249. }
  3250. return bRedFound && bBluFound;
  3251. }
  3252.  
  3253. /* CountAlivePlayers()
  3254. **
  3255. ** Retrieves the number of players alive.
  3256. ** -------------------------------------------------------------------------- */
  3257. stock int CountAlivePlayers()
  3258. {
  3259. int iCount = 0;
  3260. for (int iClient = 1; iClient <= MaxClients; iClient++)
  3261. {
  3262. if (IsValidClient(iClient, true))iCount++;
  3263. }
  3264. return iCount;
  3265. }
  3266.  
  3267. /* GetTotalClientCount()
  3268. **
  3269. ** Retrieves the number of real players connected.
  3270. ** -------------------------------------------------------------------------- */
  3271. stock int GetTotalClientCount() {
  3272. int count = 0;
  3273. for (int i = 1; i <= MaxClients; i++) {
  3274. if (IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) > 1) {
  3275. count += 1;
  3276. }
  3277. }
  3278. return count;
  3279. }
  3280.  
  3281. /* SelectTarget()
  3282. **
  3283. ** Determines a random target of the given team for the homing rocket.
  3284. ** -------------------------------------------------------------------------- */
  3285. stock int SelectTarget(int iTeam, int iRocket = -1)
  3286. {
  3287. int iTarget = -1;
  3288. float fTargetWeight = 0.0;
  3289. float fRocketPosition[3];
  3290. float fRocketDirection[3];
  3291. float fWeight;
  3292. bool bUseRocket;
  3293.  
  3294. if (iRocket != -1)
  3295. {
  3296. int iClass = g_iRocketClass[iRocket];
  3297. int iEntity = EntRefToEntIndex(g_iRocketEntity[iRocket]);
  3298.  
  3299. GetEntPropVector(iEntity, Prop_Send, "m_vecOrigin", fRocketPosition);
  3300. CopyVectors(g_fRocketDirection[iRocket], fRocketDirection);
  3301. fWeight = g_fRocketClassTargetWeight[iClass];
  3302.  
  3303. bUseRocket = true;
  3304. }
  3305.  
  3306. for (int iClient = 1; iClient <= MaxClients; iClient++)
  3307. {
  3308. // If the client isn't connected, skip.
  3309. if (!IsValidClient(iClient, true))continue;
  3310. if (iTeam && GetClientTeam(iClient) != iTeam)continue;
  3311.  
  3312. // Determine if this client should be the target.
  3313. float fNewWeight = GetURandomFloatRange(0.0, 100.0);
  3314.  
  3315. if (bUseRocket == true)
  3316. {
  3317. float fClientPosition[3]; GetClientEyePosition(iClient, fClientPosition);
  3318. float fDirectionToClient[3]; MakeVectorFromPoints(fRocketPosition, fClientPosition, fDirectionToClient);
  3319. fNewWeight += GetVectorDotProduct(fRocketDirection, fDirectionToClient) * fWeight;
  3320. }
  3321.  
  3322. if ((iTarget == -1) || fNewWeight >= fTargetWeight)
  3323. {
  3324. iTarget = iClient;
  3325. fTargetWeight = fNewWeight;
  3326. }
  3327. }
  3328.  
  3329. return iTarget;
  3330. }
  3331.  
  3332. /* StopSoundToAll()
  3333. **
  3334. ** Stops a sound for all the clients on the given channel.
  3335. ** -------------------------------------------------------------------------- */
  3336. stock void StopSoundToAll(int iChannel, const char[] strSound)
  3337. {
  3338. for (int iClient = 1; iClient <= MaxClients; iClient++)
  3339. {
  3340. if (IsValidClient(iClient))StopSound(iClient, iChannel, strSound);
  3341. }
  3342. }
  3343.  
  3344. /* PlayParticle()
  3345. **
  3346. ** Plays a particle system at the given location & angles.
  3347. ** -------------------------------------------------------------------------- */
  3348. stock void PlayParticle(float fPosition[3], float fAngles[3], char[] strParticleName, float fEffectTime = 5.0, float fLifeTime = 9.0)
  3349. {
  3350. int iEntity = CreateEntityByName("info_particle_system");
  3351. if (iEntity && IsValidEdict(iEntity))
  3352. {
  3353. TeleportEntity(iEntity, fPosition, fAngles, NULL_VECTOR);
  3354. DispatchKeyValue(iEntity, "effect_name", strParticleName);
  3355. ActivateEntity(iEntity);
  3356. AcceptEntityInput(iEntity, "Start");
  3357. CreateTimer(fEffectTime, StopParticle, EntIndexToEntRef(iEntity));
  3358. CreateTimer(fLifeTime, KillParticle, EntIndexToEntRef(iEntity));
  3359. }
  3360. else
  3361. {
  3362. LogError("ShowParticle: could not create info_particle_system");
  3363. }
  3364. }
  3365.  
  3366. /* StopParticle()
  3367. **
  3368. ** Turns of the particle system. Automatically called by PlayParticle
  3369. ** -------------------------------------------------------------------------- */
  3370. public Action StopParticle(Handle hTimer, any iEntityRef)
  3371. {
  3372. if (iEntityRef != INVALID_ENT_REFERENCE)
  3373. {
  3374. int iEntity = EntRefToEntIndex(iEntityRef);
  3375. if (iEntity && IsValidEntity(iEntity))
  3376. {
  3377. AcceptEntityInput(iEntity, "Stop");
  3378. }
  3379. }
  3380. }
  3381.  
  3382. /* KillParticle()
  3383. **
  3384. ** Destroys the particle system. Automatically called by PlayParticle
  3385. ** -------------------------------------------------------------------------- */
  3386. public Action KillParticle(Handle hTimer, any iEntityRef)
  3387. {
  3388. if (iEntityRef != INVALID_ENT_REFERENCE)
  3389. {
  3390. int iEntity = EntRefToEntIndex(iEntityRef);
  3391. if (iEntity && IsValidEntity(iEntity))
  3392. {
  3393. RemoveEdict(iEntity);
  3394. }
  3395. }
  3396. }
  3397.  
  3398. /* PrecacheParticle()
  3399. **
  3400. ** Forces the client to precache a particle system.
  3401. ** -------------------------------------------------------------------------- */
  3402. stock void PrecacheParticle(char[] strParticleName)
  3403. {
  3404. PlayParticle(view_as<float>( { 0.0, 0.0, 0.0 } ), view_as<float>( { 0.0, 0.0, 0.0 } ), strParticleName, 0.1, 0.1);
  3405. }
  3406.  
  3407. /* FindEntityByClassnameSafe()
  3408. **
  3409. ** Used to iterate through entity types, avoiding problems in cases where
  3410. ** the entity may not exist anymore.
  3411. ** -------------------------------------------------------------------------- */
  3412. stock void FindEntityByClassnameSafe(int iStart, const char[] strClassname)
  3413. {
  3414. while (iStart > -1 && !IsValidEntity(iStart))
  3415. {
  3416. iStart--;
  3417. }
  3418. return FindEntityByClassname(iStart, strClassname);
  3419. }
  3420.  
  3421. /* GetAnalogueTeam()
  3422. **
  3423. ** Gets the analogue team for this. In case of Red, it's Blue, and viceversa.
  3424. ** -------------------------------------------------------------------------- */
  3425. stock int GetAnalogueTeam(int iTeam)
  3426. {
  3427. if (iTeam == view_as<int>(TFTeam_Red))return view_as<int>(TFTeam_Blue);
  3428. return view_as<int>(TFTeam_Red);
  3429. }
  3430.  
  3431. /* ShowHiddenMOTDPanel()
  3432. **
  3433. ** Shows a hidden MOTD panel, useful for streaming music.
  3434. ** -------------------------------------------------------------------------- */
  3435. stock void ShowHiddenMOTDPanel(int iClient, char[] strTitle, char[] strMsg, char[] strType = "2")
  3436. {
  3437. Handle hPanel = CreateKeyValues("data");
  3438. KvSetString(hPanel, "title", strTitle);
  3439. KvSetString(hPanel, "type", strType);
  3440. KvSetString(hPanel, "msg", strMsg);
  3441. ShowVGUIPanel(iClient, "info", hPanel, false);
  3442. CloseHandle(hPanel);
  3443. }
  3444.  
  3445. /* PrecacheSoundEx()
  3446. **
  3447. ** Precaches a sound and adds it to the download table.
  3448. ** -------------------------------------------------------------------------- */
  3449. stock void PrecacheSoundEx(char[] strFileName, bool bPreload = false, bool bAddToDownloadTable = false)
  3450. {
  3451. char strFinalPath[PLATFORM_MAX_PATH];
  3452. Format(strFinalPath, sizeof(strFinalPath), "sound/%s", strFileName);
  3453. PrecacheSound(strFileName, bPreload);
  3454. if (bAddToDownloadTable == true)AddFileToDownloadsTable(strFinalPath);
  3455. }
  3456.  
  3457. /* PrecacheModelEx()
  3458. **
  3459. ** Precaches a models and adds it to the download table.
  3460. ** -------------------------------------------------------------------------- */
  3461. stock void PrecacheModelEx(char[] strFileName, bool bPreload = false, bool bAddToDownloadTable = false)
  3462. {
  3463. PrecacheModel(strFileName, bPreload);
  3464. if (bAddToDownloadTable)
  3465. {
  3466. char strDepFileName[PLATFORM_MAX_PATH];
  3467. Format(strDepFileName, sizeof(strDepFileName), "%s.res", strFileName);
  3468.  
  3469. if (FileExists(strDepFileName))
  3470. {
  3471. // Open stream, if possible
  3472. Handle hStream = OpenFile(strDepFileName, "r");
  3473. if (hStream == INVALID_HANDLE) { LogMessage("Error, can't read file containing model dependencies."); return; }
  3474.  
  3475. while (!IsEndOfFile(hStream))
  3476. {
  3477. char strBuffer[PLATFORM_MAX_PATH];
  3478. ReadFileLine(hStream, strBuffer, sizeof(strBuffer));
  3479. CleanString(strBuffer);
  3480.  
  3481. // If file exists...
  3482. if (FileExists(strBuffer, true))
  3483. {
  3484. // Precache depending on type, and add to download table
  3485. if (StrContains(strBuffer, ".vmt", false) != -1)PrecacheDecal(strBuffer, true);
  3486. else if (StrContains(strBuffer, ".mdl", false) != -1)PrecacheModel(strBuffer, true);
  3487. else if (StrContains(strBuffer, ".pcf", false) != -1)PrecacheGeneric(strBuffer, true);
  3488. AddFileToDownloadsTable(strBuffer);
  3489. }
  3490. }
  3491.  
  3492. // Close file
  3493. CloseHandle(hStream);
  3494. }
  3495. }
  3496. }
  3497.  
  3498. /* CleanString()
  3499. **
  3500. ** Cleans the given string from any illegal character.
  3501. ** -------------------------------------------------------------------------- */
  3502. stock void CleanString(char[] strBuffer)
  3503. {
  3504. // Cleanup any illegal characters
  3505. int Length = strlen(strBuffer);
  3506. for (int iPos = 0; iPos < Length; iPos++)
  3507. {
  3508. switch (strBuffer[iPos])
  3509. {
  3510. case '\r':strBuffer[iPos] = ' ';
  3511. case '\n':strBuffer[iPos] = ' ';
  3512. case '\t':strBuffer[iPos] = ' ';
  3513. }
  3514. }
  3515.  
  3516. // Trim string
  3517. TrimString(strBuffer);
  3518. }
  3519.  
  3520. /* FMax()
  3521. **
  3522. ** Returns the maximum of the two values given.
  3523. ** -------------------------------------------------------------------------- */
  3524. stock float FMax(float a, float b)
  3525. {
  3526. return (a > b) ? a:b;
  3527. }
  3528.  
  3529. /* FMin()
  3530. **
  3531. ** Returns the minimum of the two values given.
  3532. ** -------------------------------------------------------------------------- */
  3533. stock float FMin(float a, float b)
  3534. {
  3535. return (a < b) ? a:b;
  3536. }
  3537.  
  3538. /* GetURandomIntRange()
  3539. **
  3540. **
  3541. ** -------------------------------------------------------------------------- */
  3542. stock int GetURandomIntRange(const int iMin, const int iMax)
  3543. {
  3544. return iMin + (GetURandomInt() % (iMax - iMin + 1));
  3545. }
  3546.  
  3547. /* GetURandomFloatRange()
  3548. **
  3549. **
  3550. ** -------------------------------------------------------------------------- */
  3551. stock float GetURandomFloatRange(float fMin, float fMax)
  3552. {
  3553. return fMin + (GetURandomFloat() * (fMax - fMin));
  3554. }
  3555.  
  3556. // Pyro vision
  3557. public void tf2dodgeball_hooks(Handle convar, const char[] oldValue, const char[] newValue)
  3558. {
  3559. if (GetConVarBool(g_hCvarPyroVisionEnabled))
  3560. {
  3561. for (int i = 1; i <= MaxClients; ++i)
  3562. {
  3563. if (IsClientInGame(i))
  3564. {
  3565. TF2Attrib_SetByName(i, PYROVISION_ATTRIBUTE, 1.0);
  3566. }
  3567. }
  3568. }
  3569. else
  3570. {
  3571. for (int i = 1; i <= MaxClients; ++i)
  3572. {
  3573. if (IsClientInGame(i))
  3574. {
  3575. TF2Attrib_RemoveByName(i, PYROVISION_ATTRIBUTE);
  3576. }
  3577. }
  3578. }
  3579. if(convar == g_hMaxBouncesConVar)
  3580. g_config_iMaxBounces = StringToInt(newValue);
  3581. if(convar == g_hCvarVoteRocketClassCommandEnabled)
  3582. g_bVoteClassEnabled = view_as<bool>(StringToInt(newValue));
  3583. if(convar == g_hCvarServerChatTag)
  3584. strcopy(g_strServerChatTag, sizeof(g_strServerChatTag), newValue);
  3585. if(convar == g_hCvarMainChatColor)
  3586. strcopy(g_strMainChatColor, sizeof(g_strMainChatColor), newValue);
  3587. if(convar == g_hCvarKeywordChatColor)
  3588. strcopy(g_strKeywordChatColor, sizeof(g_strKeywordChatColor), newValue);
  3589. }
  3590.  
  3591. // Asherkins RocketBounce
  3592.  
  3593. public void OnEntityCreated(int entity, const char[] classname)
  3594. {
  3595. if (!StrEqual(classname, "tf_projectile_rocket", false))
  3596. return;
  3597.  
  3598. if (StrEqual(classname, "tf_projectile_rocket") || StrEqual(classname, "tf_projectile_sentryrocket"))
  3599. {
  3600. if (IsValidEntity(entity))
  3601. {
  3602. SetEntPropEnt(entity, Prop_Send, "m_hOriginalLauncher", entity);
  3603. SetEntPropEnt(entity, Prop_Send, "m_hLauncher", entity);
  3604. }
  3605. }
  3606.  
  3607. g_nBounces[entity] = 0;
  3608. SDKHook(entity, SDKHook_StartTouch, OnStartTouch);
  3609. }
  3610.  
  3611. public Action OnStartTouch(int entity, int other)
  3612. {
  3613. if (other > 0 && other <= MaxClients) {
  3614. if(GetConVarBool(g_hTouchAnnounce)) {
  3615. if (GetConVarBool(g_hCvarAnnounce)) {
  3616. if (GetConVarBool(g_hCvarDeflectCountAnnounce)) {
  3617. if (gDeflector == other || gDeflector == 0) {
  3618. //CPrintToChatAll("%s %s%N %sdied to their rocket travelling %s%i %smph with %s%i %sdeflections!", g_strServerChatTag, g_strKeywordChatColor, g_iLastDeadClient, g_strMainChatColor, g_strKeywordChatColor, g_iRocketSpeed, g_strMainChatColor, g_strKeywordChatColor, iDeflections, g_strMainChatColor);
  3619. CPrintToChatAll("{ORANGE}%N {DEFAULT}: Speed: {TURQUOISE}%i {DEFAULT}mph || deflections: {TURQUOISE}%i", other, g_hRocketSpeed, xDeflections);
  3620. } else {
  3621. CPrintToChatAll("%s %s%N %s- %s%.15N: Speed: %s%i %smph || deflections: %s%i", g_strServerChatTag, g_strMainChatColor, gDeflector, g_strClientChatColor, g_strMainChatColor, other, g_strKeywordChatColor, g_iRocketSpeed, g_strMainChatColor, g_strKeywordChatColor, xDeflections);
  3622. //CPrintToChatAll("%s %s%N %sdied to %s%.15N's %srocket travelling %s%i %smph with %s%i %sdeflections!", g_strServerChatTag, g_strKeywordChatColor, g_iLastDeadClient, g_strMainChatColor, g_strKeywordChatColor, iTarget, g_strMainChatColor, g_strKeywordChatColor, g_iRocketSpeed, g_strMainChatColor, g_strKeywordChatColor, iDeflections, g_strMainChatColor);
  3623. }
  3624. } else {
  3625. //CPrintToChatAll("%s %s%N %sdied to a rocket travelling %s%i %smph!", g_strServerChatTag, g_strKeywordChatColor, g_iLastDeadClient, g_strMainChatColor, g_strKeywordChatColor, g_iRocketSpeed, g_strMainChatColor);
  3626. CPrintToChatAll("%s %s%N %s- %s%.15N's: Speed: %s%i %smph", g_strServerChatTag, g_strMainChatColor, gDeflector, g_strClientChatColor, other, g_strKeywordChatColor, g_iRocketSpeed, g_strMainChatColor);
  3627. }
  3628. }
  3629. }
  3630. return Plugin_Continue;
  3631. }
  3632.  
  3633. // Only allow a rocket to bounce x times.
  3634. if (g_nBounces[entity] >= g_config_iMaxBounces)
  3635. return Plugin_Continue;
  3636.  
  3637.  
  3638. IsOnTouch = true;
  3639. SDKHook(entity, SDKHook_Touch, OnTouch);
  3640. return Plugin_Handled;
  3641. }
  3642.  
  3643. public Action OnTouch(int entity, int other)
  3644. {
  3645. float vOrigin[3];
  3646. GetEntPropVector(entity, Prop_Data, "m_vecOrigin", vOrigin);
  3647.  
  3648. float vAngles[3];
  3649. GetEntPropVector(entity, Prop_Data, "m_angRotation", vAngles);
  3650.  
  3651. float vVelocity[3];
  3652. GetEntPropVector(entity, Prop_Data, "m_vecAbsVelocity", vVelocity);
  3653.  
  3654. Handle trace = TR_TraceRayFilterEx(vOrigin, vAngles, MASK_SHOT, RayType_Infinite, TEF_ExcludeEntity, entity);
  3655.  
  3656. if (!TR_DidHit(trace))
  3657. {
  3658. CloseHandle(trace);
  3659. return Plugin_Continue;
  3660. }
  3661.  
  3662. float vNormal[3];
  3663. TR_GetPlaneNormal(trace, vNormal);
  3664.  
  3665. //PrintToServer("Surface Normal: [%.2f, %.2f, %.2f]", vNormal[0], vNormal[1], vNormal[2]);
  3666.  
  3667. CloseHandle(trace);
  3668.  
  3669. float dotProduct = GetVectorDotProduct(vNormal, vVelocity);
  3670.  
  3671. ScaleVector(vNormal, dotProduct);
  3672. ScaleVector(vNormal, 2.0);
  3673.  
  3674. float vBounceVec[3];
  3675. SubtractVectors(vVelocity, vNormal, vBounceVec);
  3676.  
  3677. float vNewAngles[3];
  3678. GetVectorAngles(vBounceVec, vNewAngles);
  3679.  
  3680. //PrintToServer("Angles: [%.2f, %.2f, %.2f] -> [%.2f, %.2f, %.2f]", vAngles[0], vAngles[1], vAngles[2], vNewAngles[0], vNewAngles[1], vNewAngles[2]);
  3681. //PrintToServer("Velocity: [%.2f, %.2f, %.2f] |%.2f| -> [%.2f, %.2f, %.2f] |%.2f|", vVelocity[0], vVelocity[1], vVelocity[2], GetVectorLength(vVelocity), vBounceVec[0], vBounceVec[1], vBounceVec[2], GetVectorLength(vBounceVec));
  3682. TeleportEntity(entity, NULL_VECTOR, vNewAngles, vBounceVec);
  3683. g_nBounces[entity]++;
  3684.  
  3685. SDKUnhook(entity, SDKHook_Touch, OnTouch);
  3686. return Plugin_Handled;
  3687. }
  3688.  
  3689. public bool TEF_ExcludeEntity(int entity, int contentsMask, any data)
  3690. {
  3691. return (entity != data);
  3692. }
  3693.  
  3694. void preventAirblast(int clientId, bool prevent)
  3695. {
  3696. int flags;
  3697.  
  3698. if (prevent == true)
  3699. {
  3700. abPrevention[clientId] = true;
  3701. flags = GetEntityFlags(clientId) | FL_NOTARGET;
  3702. }
  3703. else
  3704. {
  3705. abPrevention[clientId] = false;
  3706. flags = GetEntityFlags(clientId) & ~FL_NOTARGET;
  3707. }
  3708.  
  3709. SetEntityFlags(clientId, flags);
  3710. }
  3711.  
  3712. public Action TauntCheck(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3], int damagecustom)
  3713. {
  3714. switch (damagecustom)
  3715. {
  3716. case TF_CUSTOM_TAUNT_ARMAGEDDON:
  3717. {
  3718. damage = 0.0;
  3719. return Plugin_Changed;
  3720. }
  3721.  
  3722. }
  3723. return Plugin_Continue;
  3724. }
  3725.  
  3726. void checkStolenRocket(int clientId, int entId)
  3727. {
  3728. if (EntRefToEntIndex(g_iRocketTarget[entId]) != clientId && !bStealArray[clientId][stoleRocket])
  3729. {
  3730. bStealArray[clientId][stoleRocket] = true;
  3731. if (bStealArray[clientId][rocketsStolen] < GetConVarInt(g_hCvarStealPreventionNumber))
  3732. {
  3733. bStealArray[clientId][rocketsStolen]++;
  3734. CreateTimer(0.1, tStealTimer, GetClientUserId(clientId), TIMER_FLAG_NO_MAPCHANGE);
  3735. SlapPlayer(clientId, 0, true);
  3736. CPrintToChat(clientId, "%s %sDo not steal rockets. [Warning %s%i%s/%s%i%s]", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor, bStealArray[clientId][rocketsStolen], g_strMainChatColor, g_strKeywordChatColor, GetConVarInt(g_hCvarStealPreventionNumber), g_strMainChatColor);
  3737. }
  3738. else
  3739. {
  3740. ForcePlayerSuicide(clientId);
  3741. CPrintToChat(clientId, "%s %sYou have been slain for stealing rockets.", g_strServerChatTag, g_strMainChatColor);
  3742. CPrintToChatAll("%s %s%N %swas slain for stealing rockets.", g_strServerChatTag, g_strClientChatColor, clientId, g_strMainChatColor);
  3743. }
  3744. }
  3745. }
  3746.  
  3747. void checkRoundDelays(int entId)
  3748. {
  3749. int iEntity = EntRefToEntIndex(g_iRocketEntity[entId]);
  3750. int iTarget = EntRefToEntIndex(g_iRocketTarget[entId]);
  3751. float timeToCheck;
  3752. if (g_iRocketDeflections[entId] == 0)
  3753. timeToCheck = g_fLastSpawnTime;
  3754. else
  3755. timeToCheck = g_fRocketLastDeflectionTime[entId];
  3756.  
  3757. if (iTarget != INVALID_ENT_REFERENCE && (GetGameTime() - timeToCheck) >= GetConVarFloat(g_hCvarDelayPreventionTime))
  3758. {
  3759. g_fRocketSpeed[entId] += GetConVarFloat(g_hCvarDelayPreventionSpeedup);
  3760. if (!g_bPreventingDelay)
  3761. {
  3762. CPrintToChatAll("%s %s%N %sis delaying, the rocket will now speed up.", g_strServerChatTag, g_strClientChatColor, iTarget, g_strMainChatColor);
  3763. EmitSoundToAll(SOUND_DEFAULT_SPEEDUPALERT, iEntity, SNDCHAN_AUTO, SNDLEVEL_GUNFIRE);
  3764. }
  3765. g_bPreventingDelay = true;
  3766. }
  3767. }
  3768.  
  3769. /* SetMainRocketClass()
  3770. **
  3771. ** Takes a specified rocket class name and outputs its respective index.
  3772. ** -------------------------------------------------------------------------- */
  3773. stock int FindRocketClass(char[] class)
  3774. {
  3775. for (int i = 0; i < g_iRocketClassCount; i++)
  3776. {
  3777. if (StrContains(g_strRocketClassLongName[i], class, false) != -1)
  3778. {
  3779. return i;
  3780. }
  3781. }
  3782. return -1;
  3783. }
  3784.  
  3785. /* SetMainRocketClass()
  3786. **
  3787. ** Takes a specified rocket class index and sets it as the only rocket class able to spawn.
  3788. ** -------------------------------------------------------------------------- */
  3789. stock void SetMainRocketClass(int Index, bool isVote, int client = 0)
  3790. {
  3791. int iSpawnerClassRed = g_iSpawnPointsRedClass[g_iCurrentRedSpawn];
  3792. char strBufferRed[256];
  3793. strcopy(strBufferRed, sizeof(strBufferRed), "Red");
  3794.  
  3795. Format(strBufferRed, sizeof(strBufferRed), "%s%%", g_strRocketClassName[Index]);
  3796. SetArrayCell(g_hSpawnersChancesTable[iSpawnerClassRed], Index, 100);
  3797.  
  3798. for (int iClassIndex = 0; iClassIndex < g_iRocketClassCount; iClassIndex++)
  3799. {
  3800. if (!(iClassIndex == Index))
  3801. {
  3802. Format(strBufferRed, sizeof(strBufferRed), "%s%%", g_strRocketClassName[iClassIndex]);
  3803. SetArrayCell(g_hSpawnersChancesTable[iSpawnerClassRed], iClassIndex, 0);
  3804. }
  3805. }
  3806.  
  3807. int iSpawnerClassBlu = g_iSpawnPointsBluClass[g_iCurrentBluSpawn];
  3808. char strBufferBlue[256];
  3809. strcopy(strBufferBlue, sizeof(strBufferBlue), "Blue");
  3810.  
  3811. Format(strBufferBlue, sizeof(strBufferBlue), "%s%%", g_strRocketClassName[Index]);
  3812. SetArrayCell(g_hSpawnersChancesTable[iSpawnerClassBlu], Index, 100);
  3813.  
  3814. char strSelectionBlue[256];
  3815. strcopy(strSelectionBlue, sizeof(strBufferBlue), strBufferBlue);
  3816.  
  3817. for (int iClassIndex = 0; iClassIndex < g_iRocketClassCount; iClassIndex++)
  3818. {
  3819. if (!(iClassIndex == Index))
  3820. {
  3821. Format(strBufferBlue, sizeof(strBufferBlue), "%s%%", g_strRocketClassName[iClassIndex]);
  3822. SetArrayCell(g_hSpawnersChancesTable[iSpawnerClassBlu], iClassIndex, 0);
  3823. }
  3824. }
  3825.  
  3826. int iClass = GetRandomRocketClass(iSpawnerClassRed);
  3827. strcopy(g_strSavedClassName, sizeof(g_strSavedClassName), g_strRocketClassLongName[iClass]);
  3828.  
  3829. if (isVote)
  3830. CPrintToChatAll("%s %sVote %sfinished! %sRocket class changed to %s%s", g_strServerChatTag, g_strMainChatColor, g_strKeywordChatColor, g_strMainChatColor, g_strKeywordChatColor, g_strSavedClassName);
  3831. else CPrintToChatAll("%s %s%N %schanged the rocket class to %s%s", g_strServerChatTag, g_strClientChatColor, client, g_strMainChatColor, g_strKeywordChatColor, g_strRocketClassLongName[iClass]);
  3832. }
  3833.  
  3834. public Action tStealTimer(Handle hTimer, int iClientUid)
  3835. {
  3836. int iClient = GetClientOfUserId(iClientUid);
  3837. bStealArray[iClient][stoleRocket] = false;
  3838. }
  3839.  
  3840. /*void AttachParticle(int iEntity, char[] strParticleType)
  3841. {
  3842. int iParticle = CreateEntityByName("info_particle_system");
  3843.  
  3844. char strName[128];
  3845. if (IsValidEdict(iParticle))
  3846. {
  3847. float fPos[3];
  3848. GetEntPropVector(iEntity, Prop_Send, "m_vecOrigin", fPos);
  3849. fPos[2] += 10;
  3850. TeleportEntity(iParticle, fPos, NULL_VECTOR, NULL_VECTOR);
  3851.  
  3852. Format(strName, sizeof(strName), "target%i", iEntity);
  3853. DispatchKeyValue(iEntity, "targetname", strName);
  3854.  
  3855. DispatchKeyValue(iParticle, "targetname", "tf2particle");
  3856. DispatchKeyValue(iParticle, "parentname", strName);
  3857. DispatchKeyValue(iParticle, "effect_name", strParticleType);
  3858. DispatchSpawn(iParticle);
  3859. SetVariantString(strName);
  3860. AcceptEntityInput(iParticle, "SetParent", iParticle, iParticle, 0);
  3861. SetVariantString("");
  3862. AcceptEntityInput(iParticle, "SetParentAttachment", iParticle, iParticle, 0);
  3863. ActivateEntity(iParticle);
  3864. AcceptEntityInput(iParticle, "start");
  3865.  
  3866. g_RocketParticle[iEntity] = iParticle;
  3867. }
  3868. }*/
  3869.  
  3870. stock void CreateTempParticle(char[] particle, int entity = -1, float origin[3] = NULL_VECTOR, float angles[3] = { 0.0, 0.0, 0.0 }, bool resetparticles = false)
  3871. {
  3872. int tblidx = FindStringTable("ParticleEffectNames");
  3873.  
  3874. char tmp[256];
  3875. int stridx = INVALID_STRING_INDEX;
  3876.  
  3877. for (int i = 0; i < GetStringTableNumStrings(tblidx); i++)
  3878. {
  3879. ReadStringTable(tblidx, i, tmp, sizeof(tmp));
  3880. if (StrEqual(tmp, particle, false))
  3881. {
  3882. stridx = i;
  3883. break;
  3884. }
  3885. }
  3886.  
  3887. TE_Start("TFParticleEffect");
  3888. TE_WriteFloat("m_vecOrigin[0]", origin[0]);
  3889. TE_WriteFloat("m_vecOrigin[1]", origin[1]);
  3890. TE_WriteFloat("m_vecOrigin[2]", origin[2]);
  3891. TE_WriteVector("m_vecAngles", angles);
  3892. TE_WriteNum("m_iParticleSystemIndex", stridx);
  3893. TE_WriteNum("entindex", entity);
  3894. TE_WriteNum("m_iAttachType", 1);
  3895. TE_WriteNum("m_bResetParticles", resetparticles);
  3896. TE_SendToAll();
  3897. }
  3898.  
  3899. stock void ClearTempParticles(int client)
  3900. {
  3901. float empty[3];
  3902. CreateTempParticle("sandwich_fx", client, empty, empty, true);
  3903. }
  3904.  
  3905. /*void StolenRocket(int iClient, int iTarget)
  3906. {
  3907. if (iTarget != iClient && GetClientTeam(iClient) == GetClientTeam(iTarget))
  3908. {
  3909. PrintToChatAll("\x03%N\x01 stole \x03%N\x01's rocket!", iClient, iTarget);
  3910. g_stolen[iClient]++;
  3911. if (g_stolen[iClient] >= GetConVarInt(g_hCvarStealPreventionNumber))
  3912. {
  3913. g_stolen[iClient] = 0;
  3914. ForcePlayerSuicide(iClient);
  3915. PrintToChat(iClient, "\x03You stole %d rockets and was slayed.", g_hCvarStealPreventionNumber);
  3916. }
  3917. }
  3918. }*/
  3919.  
  3920.  
  3921. // EOF
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement