Guest User

ceva sursa

a guest
Feb 12th, 2019
188
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 67.62 KB | None | 0 0
  1. #pragma dynamic 131072 //I used to much memory =(
  2. /*
  3. * ====================================================================================================
  4. * ====================================================================================================
  5. * ---------------------------SURF_OLYMPICS-v1.5.2a--------BY: OneEyed---------------------------
  6. * ====================================================================================================
  7. * ====================================================================================================
  8. * COMMENTS:
  9. * Install the plugin normally, and get ready to beat some freagin records!
  10. * ====================================================================================================
  11. * REQUIRED:
  12. * AMXX 1.70
  13. *
  14. * MODULES:
  15. * CSTRIKE
  16. * ENGINE
  17. * FAKEMETA
  18. * NVAULT
  19. * ====================================================================================================
  20. * CVARS:
  21. * surf_flyspeed <#> - Changes flying speed of surf_endzone tool
  22. * surf_teamstack < 0 | 1 | 2 > - Forces players to be in a certain team.
  23. * surf_godmode < 0 | 1 > - Enables/Disables godmode on players.
  24. * surf_semiclip < 0 | 1 > - Enables/Disables semi-clip on players.
  25. *
  26. * COMMANDS:
  27. * surf_endzone - Enables Surf EndZone Creation Tool
  28. * surf_delete - Enables Map Record Catagory Deletion menu.
  29. * surf_on < 0 | 1 > - Enables/Disables plugin 99%.
  30. *
  31. * CHAT COMMANDS:
  32. * /spec - Makes you a spectator.
  33. * /respawn - Respawns you.
  34. * /top3 - Opens Map Top Records list.
  35. * /help - Opens help menu.
  36. *
  37. * ====================================================================================================
  38. * PLUGIN DETAILS:
  39. * When you spawn in, your in standby mode. As soon as you jump, your game is activated and your
  40. * records get recorded. Current records are Map Completion, Speed, Hang Time, Distance, and
  41. * Height. The plugin automatically respawns users when you die or fall down. Players also have
  42. * a simulated Semi-clip, so they don't get stuck inside each other, but still allow to block
  43. * each other. To complete the map, touch the designated EndZone lightning bolt.
  44. *
  45. * ====================================================================================================
  46. * CREDITS:
  47. * - Rukia found how to know if your on ladder. (drove me nuts yet it was so easy)
  48. * - teame06/VEN for HLTV event.
  49. * - teame06 help with new menu system, and Team_Select menu, and some inspiration =).
  50. * - Xtrem3 found a major hang time exploit.
  51. * - iron helix found a major height exploit.
  52. * - XAD - used the same font color from his statsx motd.
  53. * - door for helping me test some features.
  54. * - Gorlag/Batman for his Flying code.
  55. * - BASIC-MASTER, I copied his Special Effect. (not the code, just effect)
  56. * - BAILOPAN for some of the weapon removal code from CSDM v1.
  57. * - BAILOPAN, for his information on code optimization. (READ IT)
  58. * -- http://www.sourcemod.net/devlog/?p=62
  59. * ====================================================================================================
  60. * CHANGELOG:
  61. *
  62. * v1.5.2a:
  63. * - Reverted back to old method, will crash again on surf_xss and surf_maya
  64. * if you have plugins that precache models. It's the maps fault for having
  65. * to many brush models. Attempting to fix, completely breaks my plugin on normal maps.
  66. *
  67. * v1.5.2:
  68. * - Fixed crashing in surf_xss and surf_maya.
  69. *
  70. * v1.5.1:
  71. * - Fixed a bug with the semi-clip cvar.
  72. * - Fixed a entity leak error with weapon removal.
  73. *
  74. * v1.5:
  75. * - Commentator can be turned on/off through a #define.
  76. * - New CVARs:
  77. * - surf_godmode < 0 | 1 > (Turns God Mode OFF/ON, for everyone.)
  78. * - surf_semiclip < 0 | 1 > (Turns Semi-Clip OFF/ON, for everyone.)
  79. * - New Commands:
  80. * - surf_delete (Opens menu to delete records of current map.)
  81. * - surf_on < 0 | 1 > (Turns plugin OFF/ON completely.)
  82. * - Reworked Top Record System:
  83. * - One person can't dominate an entire record, there will always be three
  84. * - different players for every record catagory. Saved by STEAMID not name.
  85. * - Weapons from game_player_equip entity are removed upon death, to prevent spam.
  86. * - Players can now easily jump on top of users in Semi-Clip mode.
  87. *
  88. * v1.1:
  89. * - Changed the HUD system a little bit, to be less laggy.
  90. * - Fixed an accidental logical error with clearing airtype records.
  91. * - Blocked trigger_hurts that heal from teleporting.
  92. * - Added Personal Statistics to /top3 window.
  93. * ====================================================================================================
  94. */
  95.  
  96. /*======== User Changeable Defines =========*/
  97.  
  98. //Uncomment to add commentator text.
  99. //#define COMMENTATOR
  100.  
  101. #define STATS_COLOR_RED 255
  102. #define STATS_COLOR_GREEN 180
  103. #define STATS_COLOR_BLUE 0
  104. #define STATS_LOC_X 1.0
  105. #define STATS_LOC_Y 0.5
  106.  
  107. #define RECORDS_HUD_DELAY 7.0
  108. #define RECORD_COLOR_RED 220
  109. #define RECORD_COLOR_GREEN 80
  110. #define RECORD_COLOR_BLUE 0
  111. #define RECORD_LOC_X 1.0
  112. #define RECORD_LOC_Y 0.30
  113.  
  114. //EndZone Special Effects
  115. #define PULSE_FREQUENCY 0.4 //in seconds
  116.  
  117. #define LINE_COLOR_RED 255
  118. #define LINE_COLOR_GREEN 255
  119. #define LINE_COLOR_BLUE 255
  120.  
  121. #define WAVE_COLOR_RED 0
  122. #define WAVE_COLOR_GREEN 255
  123. #define WAVE_COLOR_BLUE 0
  124.  
  125. /*==========================================*/
  126.  
  127.  
  128. /*======================ONLY CODERS BEYOND THIS POINT!!=======================================*/
  129. /*======================ONLY CODERS BEYOND THIS POINT!!=======================================*/
  130. /*======================ONLY CODERS BEYOND THIS POINT!!=======================================*/
  131.  
  132. /*====================================================================================================
  133. How To Add A custom Record:
  134. Update the globals to add your custom record info. Scroll down to [Custom Records] and create your
  135. custom record function and math there and at the end add the template Validate_BeatRecord.
  136. If you have any global vars for your custom record, drop them inside the clean up functions, so
  137. they get reset. After that, add your custom record function inside the core named JudgeJudy.
  138. ====================================================================================================*/
  139. #include <amxmodx>
  140. #include <amxmisc>
  141. #include <engine>
  142. #include <fakemeta>
  143. #include <cstrike>
  144. #include <nvault>
  145.  
  146. new Vault
  147. static const VAULTNAME[] = "MapRecords"
  148.  
  149. new Vault_EndZone
  150. static const ENDZONE_VAULT[] = "EndZones"
  151.  
  152. #define MAX_BUFFER_LENGTH 2047
  153. #define MAX_TEXT_LENGTH 100
  154. #define MAX_PLAYERS 32
  155. /****************************************************/
  156. /**************** Editable Globals ******************/
  157.  
  158. #define NUMRANKS 3
  159. #define NUMRECORDS 5
  160.  
  161. //Record Types in order.
  162. enum {
  163. COMPLETION = 1,
  164. SPEED,
  165. HANGTIME,
  166. DISTANCE,
  167. HEIGHT
  168. }
  169.  
  170. //These records require players to be in the air for recording.
  171. #define NUM_AIR_RECORDS 3
  172. new AIR_RECORDS[NUM_AIR_RECORDS] = {
  173. HANGTIME,
  174. DISTANCE,
  175. HEIGHT
  176. }
  177.  
  178. //These records are read at all times.
  179. #define NUM_ANYTIME_RECORDS 1
  180. new ANYTIME_RECORDS[NUM_ANYTIME_RECORDS] = {
  181. SPEED
  182. }
  183.  
  184. //I predefined up to 7th rank. Be warned, show_motd can only hold 2047 characters in total.
  185. //4 ranks uses nearly all that. So some changes will need to be made if u want to display more.
  186. //You shouldn't need more than 4, cause the records end up being very close to each other.
  187. static const RANKS[NUMRANKS+1][] = {
  188. "NULL",
  189. "st",
  190. "nd",
  191. "rd"
  192. /* "th",
  193. "th",
  194. "th",
  195. "th" */
  196. }
  197.  
  198. //The Titles order must match enum up top.
  199. static const TITLES[NUMRECORDS+1][] = {
  200. "NULL",
  201. "Completion",
  202. "Speed",
  203. "Hang Time",
  204. "Distance",
  205. "Height"
  206. }
  207.  
  208. //symbols records use, order must match enum up top.
  209. static const TYPES[NUMRECORDS+1][] = { "NULL", "sec", "mph", "sec", "ft", "ft" }
  210.  
  211. #if defined COMMENTATOR
  212. static const BAD_COMMENT[4][] = {
  213. "Wipe Out!",
  214. "OUCH!",
  215. "That's gotta hurt!",
  216. "Try Again!"
  217. }
  218.  
  219. static const GOOD_COMMENT[5][] = {
  220. "Way to go!",
  221. "Awesome!",
  222. "Nice!",
  223. "Spectacular!",
  224. "That's OUTRAGEOUS!"
  225. }
  226. #endif
  227.  
  228.  
  229. /****************************************************/
  230. /**************** Record Variables ******************/
  231.  
  232. //Saved Personal Best Record
  233. new Float:g_fPersonalRecord[MAX_PLAYERS+1][NUMRECORDS+1]
  234. //Current Record of current run (prevents multiple records for top records in one jump)
  235. new Float:g_fPersonalOld[MAX_PLAYERS+1][NUMRECORDS+1]
  236. //Top Records of map 1st/2nd/3rd
  237. new Float:g_fTopRecord[NUMRECORDS+1][NUMRANKS+1]
  238.  
  239. //For quick data accessing
  240. new g_TopRecordName[NUMRECORDS+1][NUMRANKS+1][MAX_TEXT_LENGTH+1]
  241. new g_TopRecordSteamId[NUMRECORDS+1][NUMRANKS+1][MAX_TEXT_LENGTH+1]
  242.  
  243. /****************************************************/
  244. /************ Custom Record Variables ***************/
  245.  
  246. new Float:g_fTimeElapsed[MAX_PLAYERS+1]
  247. new Float:g_fvecEndOrigin[MAX_PLAYERS+1][3] //Where we currently are.
  248. new Float:g_fvecPrevOrigin[MAX_PLAYERS+1][3] //For Teleport Menu (Prev Location).
  249. new Float:g_fHeight[MAX_PLAYERS+1] //Height we reached.
  250. new g_vecStartOrigin[MAX_PLAYERS+1][3] //Where we took off from wave/jump.
  251. new bool:g_bDistCheck[MAX_PLAYERS+1] //When to calculate distance.
  252.  
  253. /****************************************************/
  254. /****************** Event Flags *********************/
  255.  
  256. new Float:g_Gametime
  257. new Float:g_fShowHudDelay[MAX_PLAYERS+1]
  258.  
  259. new Float:g_fIsInAir[MAX_PLAYERS+1] //If this is not equal to current get_gametime(), player is in AIR.
  260. new bool:g_bPlaystarted[MAX_PLAYERS+1]
  261. new bool:g_bRespawning[MAX_PLAYERS+1]
  262. new bool:g_bPlaying[MAX_PLAYERS+1]
  263. new bool:g_bIsDead[MAX_PLAYERS+1]
  264.  
  265. //record beating flags, so we don't update only once... appropriately
  266. new bool:g_bCheckPersonal[MAX_PLAYERS+1][NUMRECORDS+1]
  267. new bool:g_bCheckTop[MAX_PLAYERS+1][NUMRECORDS+1]
  268.  
  269.  
  270. /****************************************************/
  271. /**************** Hud Text Messages *****************/
  272.  
  273. new g_StatText[MAX_PLAYERS+1][NUMRECORDS + 1][MAX_TEXT_LENGTH + 1]
  274. new g_RecordText[MAX_PLAYERS+1][NUMRECORDS + 1][MAX_TEXT_LENGTH + 1]
  275.  
  276. new HudText_Records[MAX_BUFFER_LENGTH + 1]
  277. new HudText_Stats[MAX_BUFFER_LENGTH + 1]
  278.  
  279. /****************************************************/
  280. /****************** Misc Variables ******************/
  281. new bool:g_bIsSurf
  282. new bool:g_bRunOnce
  283. new g_Maxplayers
  284. new g_MapName[64]
  285. new g_EndRound
  286. new g_NoClip
  287.  
  288. //endzone misc.
  289. new bool:g_bModifyMode[MAX_PLAYERS+1]
  290. new bool:g_IsFlying[MAX_PLAYERS+1]
  291. new bool:g_bFinished[MAX_PLAYERS+1]
  292.  
  293. //menus
  294. new menu_teleport
  295. new menu_modify[MAX_PLAYERS+1]
  296. new menu_finished[MAX_PLAYERS+1]
  297. new menu_help
  298. new menu_savecheck
  299. new menu_deletecheck
  300. new menu_deleterecords
  301.  
  302. /****************************************************/
  303. /************** Special FX Variables ****************/
  304.  
  305. new g_fxBeamSprite, g_fxWave
  306.  
  307. /****************************************************/
  308. /**************** Entity Variables ******************/
  309.  
  310. //game_player_equip weapons
  311. new g_StartWeap[32][64]
  312. new g_TotalWeap
  313. //teleport destinations
  314. new g_TotalTeleDest
  315. new g_TeleDest[100][32]
  316. new g_TeleDestId[100]
  317. //trigger_teleports
  318. new g_TotalTeleports
  319. new g_TriggerTeleport[100][32]
  320. new g_TriggerTeleId[100]
  321. //trigger hurts with healing
  322. new g_TriggerHurtHealers[100]
  323. new g_TrigHurtHealTotal
  324. //linked info_target_destination & trigger_teleport
  325. new g_LinkedTeleAndDest[100][2]
  326. new g_TotalLinked
  327. //spawns info
  328. new g_InfoPlayerStart
  329. new g_InfoPlayerDeathmatch
  330. new bool:g_bBothTeamsActive
  331. //EndZone Vars
  332. new g_EndzoneEntity
  333. static const ENDZONE_MODEL[] = "models/chick.mdl" //this will be invisible (needed to set a bounding box)
  334. /****************************************************/
  335. //====================================================================================================
  336. static const TITLE[] = "surf_olympics"
  337. static const VERSION[] = "1.5.2a"
  338. static const AUTHOR[] = "OneEyed"
  339. //====================================================================================================
  340.  
  341.  
  342. /*====================================================================================================
  343. [Initialize]
  344.  
  345. Purpose: Prepares the map by automating a bunch of information at start of map, so plugin won't lag
  346. during gameplay. Also validates if we're on a SURF_MAP. If not plugin disables itself
  347. 100%.
  348.  
  349. Comment: Added CVAR for internet query lookup of plugin.
  350.  
  351. ====================================================================================================*/
  352. public plugin_init() {
  353. register_plugin(TITLE,VERSION,AUTHOR)
  354. register_cvar(TITLE,"0",FCVAR_SERVER)
  355.  
  356. if(g_bIsSurf)
  357. set_cvar_num(TITLE,1)
  358. else {
  359. set_cvar_num(TITLE,0)
  360. return PLUGIN_HANDLED
  361. }
  362.  
  363. PRECACHE_MODELS()
  364.  
  365. g_Maxplayers = get_maxplayers()
  366.  
  367. //Find if map is missing a teams spawn points.
  368. if(g_InfoPlayerDeathmatch == 0 || g_InfoPlayerStart == 0)
  369. g_bBothTeamsActive = true
  370.  
  371. LoadMenus()
  372.  
  373. register_cvar("surf_flyspeed","1500")
  374. register_cvar("surf_teamstack","0")
  375. register_cvar("surf_semiclip","1")
  376. register_cvar("surf_godmode","0")
  377.  
  378. register_clcmd("say /spec","cmdSpectate")
  379. //register_clcmd("say /respawn","cmdRespawn")
  380. //register_clcmd("say_team /respawn","cmdRespawn")
  381. register_clcmd("say /top3","recordLookUp")
  382. register_clcmd("say_team /top3","recordLookUp")
  383. register_clcmd("say","handle_say")
  384. register_clcmd("say_team", "handle_say")
  385.  
  386. register_concmd("surf_on","cmdEnable",ADMIN_RCON,"<0|1> Enable / Disable Surf Olympics")
  387. register_concmd("surf_delete","cmdDeleteRecords",ADMIN_RCON, " Deletes Top Map Records by Type.")
  388. register_concmd("surf_endzone","cmdEZModify",ADMIN_RCON," Easy Endzone Creator!")
  389.  
  390.  
  391. register_menucmd(register_menuid("Team_Select",1), (1<<0)|(1<<1)|(1<<4)|(1<<5), "team_select")
  392.  
  393. register_event("DeathMsg", "Event_DeathMsg", "a")
  394. register_event("ResetHUD", "Event_ResetHUD", "be")
  395. register_event("SendAudio","Event_EndRound","a","2=%!MRAD_terwin","2=%!MRAD_ctwin","2=%!MRAD_rounddraw")
  396. register_event("TextMsg","Event_EndRound","a","1=4","2=#Game_Commencing")
  397. register_event("HLTV","Event_StartRound","a","1=0","2=0")
  398.  
  399. register_touch("trigger_hurt", "player", "Touch_TriggerHurt")
  400. register_touch("trigger_teleport", "player", "Touch_Teleport")
  401.  
  402. //These are our slopes, considered like your in the air to EV_INT_flags so we need them.
  403. register_touch("player", "worldspawn", "Touch_World")
  404. register_touch("player", "func_water", "Touch_World")
  405. register_touch("player", "func_wall", "Touch_World")
  406. register_touch("player", "func_breakable", "Touch_World")
  407.  
  408. register_touch("EndZone", "player", "Touch_EndZone")
  409. register_touch("player", "player", "Touch_Player")
  410.  
  411. //CORE Loop
  412. //Meanest bitch of the south!
  413. new judge = create_entity("info_target")
  414. if (judge) {
  415. entity_set_string(judge, EV_SZ_classname, "JudgeJudy")
  416. entity_set_float(judge, EV_FL_nextthink, halflife_time() + 0.1)
  417. register_think("JudgeJudy", "JudgeJudy")
  418. }
  419.  
  420. register_think("EndZone","setEffects")
  421.  
  422. LoadRecords()
  423. return PLUGIN_HANDLED
  424. }
  425.  
  426. PRECACHE_MODELS() {
  427. if(g_bIsSurf) {
  428. engfunc( EngFunc_PrecacheModel, "models/chick.mdl");
  429. g_fxBeamSprite = engfunc( EngFunc_PrecacheModel,"sprites/lgtning.spr")//engfunc( EngFunc_PrecacheModel,
  430. g_fxWave = engfunc( EngFunc_PrecacheModel,"sprites/shockwave.spr")//engfunc( EngFunc_PrecacheModel,
  431. }
  432. }
  433.  
  434. /*====================================================================================================
  435. [Core]
  436.  
  437. Purpose: This is the core, it runs every 0.1 seconds. Scans through all players. Works by knowing
  438. when player enters team, dies, jumps to begin session, if player is in the air for record
  439. logging, and prints their HUD of information. All record checks are activated here, except
  440. for map completion.
  441.  
  442. Comment: The core of the plugin lies in Judge Judy's hands, so RESPECT!
  443. If your smart, you can add your own custom records to it.
  444.  
  445. ====================================================================================================*/
  446. public JudgeJudy(judge) {
  447.  
  448. if(!g_EndRound && g_bIsSurf) {
  449.  
  450. g_Gametime = get_gametime()
  451. g_NoClip = get_cvar_num("surf_semiclip")
  452.  
  453. for(new id=1;id<=g_Maxplayers;id++) {
  454.  
  455. if(!is_user_connected(id) || g_bModifyMode[id]) continue
  456.  
  457. new team = get_user_team(id)
  458. if( team == 1 || team == 2 )
  459. {
  460. if(!g_bBothTeamsActive)
  461. check_team(id,team)
  462.  
  463. if(!is_user_alive(id)) {
  464. if(!g_bIsDead[id]) {
  465. g_bIsDead[id] = true
  466. set_task(0.5,"AutoRespawn",id)
  467. }
  468. g_fIsInAir[id] = g_Gametime + 0.1
  469. continue
  470. }
  471.  
  472. //part of semi-clip
  473. if(entity_get_int(id,EV_INT_solid) != SOLID_BBOX)
  474. entity_set_int(id,EV_INT_solid,SOLID_BBOX)
  475.  
  476. new flags = entity_get_int(id, EV_INT_flags)
  477. new grounded = on_ground(id,flags)
  478. new bool:playstarted2 = g_bPlaystarted[id]
  479.  
  480. // Time Elapsed Timer
  481. showTimeElapsed(id,playstarted2)
  482.  
  483. //Player just spawned/teleported in, don't start anything until they touch ground
  484. if(!g_bPlaying[id]) {
  485. if(grounded) {
  486. clearAirRecords(id)
  487. g_bPlaying[id] = true
  488. }
  489. continue
  490. }
  491. else {
  492.  
  493. entity_get_vector(id,EV_VEC_origin,g_fvecEndOrigin[id])
  494. //player on ground.
  495. if(grounded)
  496. {
  497. Validate_AirChecks(id)
  498. clearAirRecords(id)
  499.  
  500. }
  501. else if(g_fIsInAir[id] < g_Gametime) //We're in the air do your stuff quickly.
  502. {
  503. if(!playstarted2) //Player jumped lets begin recording everything
  504. {
  505. g_fTimeElapsed[id] = g_Gametime
  506. playstarted2 = true
  507. }
  508.  
  509. if(flags & FL_BASEVELOCITY) //Block Trigger_Push Exploit (but still update HUD)
  510. clearAirRecords(id)
  511.  
  512. if(g_bRespawning[id]) { //Fix Teleport/Respawn exploit
  513. g_bRespawning[id] = false
  514. clearAirRecords(id)
  515. }
  516.  
  517. /*Records that require player in air*/
  518. Check_Distance(id)
  519. Check_Height(id)
  520. Check_HangTime(id)
  521. /************************************/
  522. }
  523.  
  524. /*Records of player at all times*/
  525. Check_Speed(id)
  526. /*******************************/
  527. }
  528.  
  529. g_bPlaystarted[id] = playstarted2
  530.  
  531. showStats(id) //Display HUD
  532.  
  533. }
  534. else {
  535. if(g_NoClip && entity_get_int(id,EV_INT_solid) != SOLID_NOT)
  536. entity_set_int(id, EV_INT_solid, SOLID_NOT)
  537. }
  538. }
  539. }
  540. entity_set_float(judge, EV_FL_nextthink, halflife_time() + 0.1)
  541. }
  542.  
  543. /*====================================================================================================
  544. [Display HUD]
  545.  
  546. Purpose: Displays Records/Stats to users. show Records is displayed when user respawns/uses command.
  547. showStats displays when user is playing.
  548.  
  549. Comment: $$
  550.  
  551. ====================================================================================================*/
  552. public showRecords(id)
  553. {
  554. if((g_Gametime - g_fShowHudDelay[id]) > (RECORDS_HUD_DELAY + 1.0))
  555. {
  556. new rLen = format(HudText_Records, MAX_BUFFER_LENGTH, "Record Statistics")
  557.  
  558. for( new x = 2 ; x <= NUMRECORDS ; x++ )
  559. rLen += format(HudText_Records[rLen], MAX_BUFFER_LENGTH-rLen, "%s", g_RecordText[id][x])
  560.  
  561. rLen += format(HudText_Records[rLen], MAX_BUFFER_LENGTH-rLen, "%s", g_RecordText[id][COMPLETION])
  562.  
  563. set_hudmessage(RECORD_COLOR_RED, RECORD_COLOR_GREEN, RECORD_COLOR_BLUE, RECORD_LOC_X, RECORD_LOC_Y, 1, 3.0, RECORDS_HUD_DELAY, 0.0, 1.0, 5)
  564. show_hudmessage(id,"%s",HudText_Records)
  565. g_fShowHudDelay[id] = g_Gametime
  566. }
  567.  
  568. }
  569.  
  570. public showTimeElapsed(id, bool:started) {
  571. if(g_EndzoneEntity && !g_bFinished[id] && started)
  572. {
  573. format(g_StatText[id][COMPLETION],MAX_TEXT_LENGTH,"^nTime Elapsed %.1f sec",(g_Gametime - g_fTimeElapsed[id]))
  574.  
  575. set_hudmessage(STATS_COLOR_RED, STATS_COLOR_GREEN, STATS_COLOR_BLUE, -1.0, 0.0, 0, 0.0, 0.3, 0.0, 0.0, 4)
  576. show_hudmessage(id,"%s",g_StatText[id][COMPLETION])
  577. }
  578. else
  579. g_StatText[id][COMPLETION][0] = 0
  580. }
  581.  
  582. public showStats(id)
  583. {
  584. HudText_Stats[0] = 0
  585. new sLen = 0
  586. for( new x = 2 ; x <= NUMRECORDS ; x++ )
  587. sLen += format(HudText_Stats[sLen], MAX_BUFFER_LENGTH-sLen, "%s", g_StatText[id][x])
  588.  
  589. set_hudmessage(STATS_COLOR_RED, STATS_COLOR_GREEN, STATS_COLOR_BLUE, STATS_LOC_X, STATS_LOC_Y, 0, 0.0, 0.3, 0.0, 0.0, 3)
  590. show_hudmessage(id,"%s",HudText_Stats)
  591.  
  592. }
  593.  
  594. /*====================================================================================================
  595. [Custom Records]
  596.  
  597. Purpose: Our record keepings are done here.
  598.  
  599. Comment: Use the template Validate_BeatRecord for custom records if you want records to be
  600. beaten more than once in an entire run. Unlike check completion, which is checked once when
  601. player reaches endzone.
  602.  
  603. ====================================================================================================*/
  604.  
  605. Check_HangTime(id)
  606. {
  607. //check for a serious ladder exploit
  608. new startEnt, cine[64]
  609. while((startEnt = find_ent_in_sphere(startEnt,g_fvecEndOrigin[id],45.0)) != 0)
  610. {
  611. if(is_user_connected(startEnt) || !is_valid_ent(startEnt)) continue
  612.  
  613. entity_get_string(startEnt,EV_SZ_classname,cine,63)
  614. if(equal(cine,"func_ladder")) {
  615. g_fIsInAir[id] = g_Gametime
  616. return PLUGIN_HANDLED
  617. }
  618. }
  619.  
  620. new Float:pHangtime = (g_Gametime - g_fIsInAir[id])
  621. Validate_BeatRecord(id, HANGTIME, pHangtime)
  622.  
  623. return PLUGIN_HANDLED
  624. }
  625.  
  626. Check_Speed(id) {
  627. new Float:pSpeed = float(get_speed(id)) / 18.0
  628. Validate_BeatRecord(id, SPEED, pSpeed)
  629. }
  630.  
  631. Check_Distance(id) {
  632.  
  633. if(g_bDistCheck[id])
  634. {
  635.  
  636. g_vecStartOrigin[id][0] = floatround(g_fvecEndOrigin[id][0])
  637. g_vecStartOrigin[id][1] = floatround(g_fvecEndOrigin[id][1])
  638.  
  639. g_bDistCheck[id] = false
  640. }
  641. else
  642. {
  643. new newdist[3]
  644. newdist[0] = floatround(g_fvecEndOrigin[id][0])
  645. newdist[1] = floatround(g_fvecEndOrigin[id][1])
  646.  
  647. new Float:pDist = float(get_distance(g_vecStartOrigin[id],newdist)) / 16.5
  648. Validate_BeatRecord(id, DISTANCE, pDist)
  649. }
  650. }
  651.  
  652. Check_Height(id) {
  653.  
  654. new Float:jHeight = (g_fvecEndOrigin[id][2] - g_fHeight[id]) / 8.0
  655.  
  656. if(jHeight < 0.0) return
  657.  
  658. Validate_BeatRecord(id, HEIGHT, jHeight)
  659.  
  660. return
  661. }
  662.  
  663. Float:Check_Completion(id) {
  664. //use get_gametime() to get a more accurate reading.
  665. new Float:fCompletion = get_gametime() - g_fTimeElapsed[id]
  666.  
  667. format(g_StatText[id][COMPLETION],MAX_TEXT_LENGTH,"^nMap Completed in %.2f seconds",fCompletion)
  668.  
  669. if(fCompletion < g_fPersonalRecord[id][COMPLETION]) {
  670. g_fPersonalRecord[id][COMPLETION] = fCompletion
  671. format(g_RecordText[id][COMPLETION],MAX_TEXT_LENGTH,"^nCompletion -- %.2f sec",fCompletion)
  672. }
  673.  
  674. g_fPersonalOld[id][COMPLETION] = fCompletion
  675.  
  676. Check_TopRecord(id, COMPLETION, 1)
  677.  
  678. return fCompletion
  679. }
  680.  
  681. /*====================================================================================================
  682. [Validation]
  683.  
  684. Purpose: If we beat a personal record, automatically update it. If we beat a Top 3 record, do
  685. a check to find what rank our player reached. Cascade our top_records down a rank respectively.
  686.  
  687. Comment: If you add a custom record, use the Validate BeatRecord template.
  688.  
  689. ====================================================================================================*/
  690. Validate_BeatRecord(id, recordtype, Float:jRecord) {
  691.  
  692. //Format HUD Stat String of recordtype
  693. format(g_StatText[id][recordtype], MAX_TEXT_LENGTH, "^n%s -- %.2f %s", TITLES[recordtype], jRecord, TYPES[recordtype])
  694.  
  695. //If our running statistic beats players record of current session, update it
  696. //and check if it beat a personal/top record, if so, mark its flag.
  697. if(jRecord > g_fPersonalOld[id][recordtype])
  698. {
  699. g_fPersonalOld[id][recordtype] = jRecord //save their best (for current session)
  700.  
  701. if(jRecord > g_fPersonalRecord[id][recordtype]) // beat their own record
  702. g_bCheckPersonal[id][recordtype] = true
  703.  
  704. if(jRecord > g_fTopRecord[recordtype][NUMRANKS]) //beat lowest rank
  705. g_bCheckTop[id][recordtype] = true
  706. }
  707. }
  708.  
  709. //Validate our checks
  710. Validate_AirChecks(id)
  711. {
  712. for( new x = 0 ; x < NUM_AIR_RECORDS ; x++ )
  713. {
  714. if(g_bCheckPersonal[id][AIR_RECORDS[x]])
  715. Set_PersonalRecord(id, AIR_RECORDS[x])
  716.  
  717. if(g_bCheckTop[id][AIR_RECORDS[x]])
  718. Check_TopRecord(id, AIR_RECORDS[x], 0)
  719. }
  720. }
  721.  
  722. Validate_OtherChecks(id)
  723. {
  724. for( new x = 0 ; x < NUM_ANYTIME_RECORDS ; x++ )
  725. {
  726. if(g_bCheckPersonal[id][ANYTIME_RECORDS[x]])
  727. Set_PersonalRecord(id, ANYTIME_RECORDS[x])
  728.  
  729. if(g_bCheckTop[id][ANYTIME_RECORDS[x]])
  730. Check_TopRecord(id, ANYTIME_RECORDS[x], 0)
  731. }
  732. }
  733.  
  734. //Update their Personal Record
  735. Set_PersonalRecord(id, recordtype) {
  736.  
  737. new Float:jRecord = g_fPersonalOld[id][recordtype]
  738. format(g_RecordText[id][recordtype], MAX_TEXT_LENGTH, "^n%s -- %.2f %s", TITLES[recordtype], jRecord, TYPES[recordtype])
  739.  
  740. g_fPersonalRecord[id][recordtype] = jRecord
  741. g_bCheckPersonal[id][recordtype] = false
  742. }
  743.  
  744. Check_TopRecord(id, recordtype, iftype)
  745. {
  746. new hasrank, authid[32], x
  747. get_user_authid(id,authid,31)
  748.  
  749. //Do we have a record in the list?
  750. for( x = 1 ; x <= NUMRANKS ; x++ )
  751. if(equali(g_TopRecordSteamId[recordtype][x][0],authid)) {
  752. hasrank = x
  753. break
  754. }
  755.  
  756. new endrank = ( (hasrank > 0) ? hasrank : NUMRANKS )
  757. new Float:jRecord = g_fPersonalOld[id][recordtype]
  758.  
  759. //Difference is the greaterthan / lesserthan signs
  760. switch(iftype) {
  761. case 0: {
  762. for( x = 1 ; x <= endrank ; x++ )
  763. if(jRecord > g_fTopRecord[recordtype][x]) {
  764. Set_TopRecord(id, authid, recordtype, x, jRecord, hasrank)
  765. break
  766. }
  767. }
  768. case 1: {
  769. for( x = 1 ; x <= endrank ; x++ )
  770. if(jRecord < g_fTopRecord[recordtype][x]) {
  771. Set_TopRecord(id, authid, recordtype, x, jRecord, hasrank)
  772. break
  773. }
  774. }
  775. }
  776. g_bCheckTop[id][recordtype] = false
  777. }
  778. //We don't allow double records, only update users record.
  779. Set_TopRecord(id, authid[], recordtype, rank, Float:jRecord, hasrank)
  780. {
  781.  
  782. new name[MAX_TEXT_LENGTH+1]
  783. get_user_name(id,name,MAX_TEXT_LENGTH)
  784.  
  785. replace(name,MAX_TEXT_LENGTH,"<","(") //These symbols screw up html,
  786. replace(name,MAX_TEXT_LENGTH,">",")") //if user has them in their name.
  787. replace(name,MAX_TEXT_LENGTH,"&","&amp;")
  788.  
  789. new temp, x
  790.  
  791. if(hasrank) //Update according to their current saved rank.
  792. {
  793. for( x = hasrank; x >= rank ; x-- )
  794. if(x == rank)
  795. saveRecord(authid, name, rank, recordtype, jRecord)
  796. else {
  797. temp = x-1 //temp rank (helps amxx run faster)
  798. saveRecord(g_TopRecordSteamId[recordtype][temp], g_TopRecordName[recordtype][temp], x, recordtype, g_fTopRecord[recordtype][temp])
  799. }
  800. }
  801. else //No saved rank, cascade ranks down from current
  802. {
  803. for( x = NUMRANKS; x >= rank ; x-- )
  804. if(x == rank)
  805. saveRecord(authid, name, x, recordtype, jRecord)
  806. else {
  807. temp = x-1 //temp rank (helps amxx run faster)
  808. saveRecord(g_TopRecordSteamId[recordtype][temp], g_TopRecordName[recordtype][temp], x, recordtype, g_fTopRecord[recordtype][temp])
  809. }
  810. }
  811. }
  812.  
  813. /*====================================================================================================
  814. [Touched]
  815.  
  816. Purpose: These functions are for certain events for when player touches what we specified.
  817. Mostly record checks.
  818.  
  819. Comment: $$
  820.  
  821. ====================================================================================================*/
  822. public Touch_Teleport(teleport, id) {
  823. if(!g_EndRound && g_bIsSurf) {
  824.  
  825. g_bRespawning[id] = true
  826.  
  827. //If player touches teleport, check their records immediately if they have one
  828. Validate_AirChecks(id)
  829.  
  830. //same as above
  831. Validate_OtherChecks(id)
  832.  
  833. #if defined COMMENTATOR
  834. new rand = random_num(0,3)
  835. client_print(id, print_chat, "%s", GOOD_COMMENT[rand])
  836. #endif
  837. }
  838. }
  839.  
  840. //stop players stucking inside each other, still allow semi block
  841. public Touch_Player(id, otherPlayer)
  842. {
  843. if(!g_bModifyMode[id] && !g_bModifyMode[otherPlayer] && g_bIsSurf)
  844. {
  845.  
  846. clearAirRecords(id) //Exploit Fix.
  847.  
  848. if(g_NoClip) {
  849. if(entity_get_int(id, EV_INT_solid) != SOLID_NOT)
  850. entity_set_int(id, EV_INT_solid, SOLID_NOT)
  851. if(entity_get_int(otherPlayer, EV_INT_solid) != SOLID_NOT)
  852. entity_set_int(otherPlayer, EV_INT_solid, SOLID_NOT)
  853.  
  854. //Allow players to jump/stack on each other
  855. new buttonPressed = entity_get_int(id, EV_INT_button)
  856. if( (buttonPressed & IN_JUMP) ) {
  857. new Float:jVel[3]
  858. entity_get_vector(id,EV_VEC_velocity,jVel)
  859. jVel[2] = 375.0
  860. entity_set_vector(id,EV_VEC_velocity,jVel)
  861. }
  862. }
  863. }
  864. }
  865.  
  866. //touched func_wall/worldspawn/func_water
  867. public Touch_World(id, world) {
  868. if(!g_EndRound && g_bIsSurf)
  869. {
  870. if(!g_bRespawning[id])
  871. Validate_AirChecks(id)
  872.  
  873. clearAirRecords(id)
  874. }
  875. return PLUGIN_HANDLED
  876. }
  877.  
  878. //respawn player, compensate for if olympics is turned off
  879. public Touch_TriggerHurt(hurt, id)
  880. {
  881. if(is_user_alive(id))
  882. {
  883. new bool:check
  884. for(new x=0;x<g_TrigHurtHealTotal;x++) //Allow hurts to heal.
  885. if(g_TriggerHurtHealers[x] == hurt)
  886. check = true
  887.  
  888. if(g_bIsSurf)
  889. {
  890. if(!g_bModifyMode[id] && !check)
  891. {
  892. g_bRespawning[id] = true
  893.  
  894. //Only need OtherChecks here
  895. Validate_OtherChecks(id)
  896.  
  897.  
  898. AutoRespawn(id)
  899.  
  900. #if defined COMMENTATOR
  901. new rand = random_num(0,3)
  902. client_print(id, print_chat, "%s", BAD_COMMENT[rand])
  903. #endif
  904. }
  905. }
  906. else
  907. if(!check)
  908. user_kill(id) //since we removed dmg
  909. }
  910. }
  911.  
  912. //Player touched EndZone entity
  913. public Touch_EndZone(ezone, id) {
  914. if(!g_EndRound && !g_bModifyMode[id] && !g_bFinished[id] && g_bIsSurf) {
  915. g_bFinished[id] = true
  916.  
  917. Validate_OtherChecks(id)
  918.  
  919. new Float:tempVel[3], Float:tempOrig[3]
  920. entity_get_vector(ezone, EV_VEC_origin, tempOrig)
  921. entity_set_origin(id, tempOrig)
  922. entity_set_vector(id, EV_VEC_velocity, tempVel)
  923.  
  924. new Float:completion = Check_Completion(id)
  925. new menuName[64]
  926. format(menuName, 63, "Map Completed in %.2f seconds!", completion)
  927. menu_finished[id] = menu_create(menuName, "finished_handler")
  928. menu_additem(menu_finished[id], "Start Over", "1", 0)
  929. menu_additem(menu_finished[id], "Keep Playing", "2", 0)
  930. menu_setprop(menu_finished[id], MPROP_EXIT, MEXIT_NEVER);
  931. menu_display(id, menu_finished[id], 0)
  932.  
  933. showRecords(id)
  934. }
  935. }
  936. //This goes connected with touchedEndZone
  937. public finished_handler(id, menu, item) {
  938. if(is_user_connected(id)) {
  939. new cmd[6], iName[64];
  940. new access, callback;
  941. menu_item_getinfo(menu, item, access, cmd,5, iName, 63, callback);
  942.  
  943. switch(str_to_num(cmd)) {
  944. case 1: {
  945. AutoRespawn(id)
  946. }
  947. case 2: {
  948. if(g_bFinished[id])
  949. client_print(id, print_chat, "[Surf Olympics] - Type /respawn when your ready to start again.")
  950. }
  951. }
  952. }
  953. }
  954.  
  955. //NEVER CHANGE!!
  956. on_ground(id, flags) {
  957. new movetype = entity_get_int(id,EV_INT_movetype)
  958. if( (movetype == 5) || (flags & FL_ONGROUND) || (flags & FL_PARTIALGROUND) ||
  959. (flags & FL_INWATER) || (flags & FL_CONVEYOR) || (flags & FL_FLOAT) )
  960. return 1
  961. return 0
  962. }
  963.  
  964. /*====================================================================================================
  965. [Clean Up]
  966.  
  967. Purpose: Clean up all the crap so player doesn't exploit by accident.
  968.  
  969. Comment: If you add a custom record, clean up your variables here.
  970.  
  971. ====================================================================================================*/
  972.  
  973. //CLEANUP EVERYTHING
  974. public cleanup(id) {
  975. for( new x = 1 ; x <= NUMRANKS ; x++ ) {
  976. g_bCheckPersonal[id][x] = false
  977. g_bCheckTop[id][x] = false
  978. }
  979.  
  980. for( new x = 2 ; x <= NUMRECORDS ; x++ ) {
  981. g_fPersonalOld[id][x] = 0.0
  982. }
  983.  
  984. if(g_bFinished[id])
  985. {
  986. g_bFinished[id] = false
  987.  
  988. new men, newmenu
  989. player_menu_info(id, men, newmenu)
  990. if(newmenu == menu_finished[id]) //close our finished menu
  991. client_cmd(id,"slot2")
  992. }
  993. //CORE variables
  994. g_fTimeElapsed[id] = 0.0
  995. g_bPlaying[id] = false
  996. g_bPlaystarted[id] = false
  997.  
  998. //make AIR RECORD vars equal less than 0 to your Checks
  999. g_fHeight[id] = 9999.0
  1000. g_bDistCheck[id] = true
  1001. g_fIsInAir[id] = 999999.0
  1002. }
  1003.  
  1004. //Clear AIR RECORDs
  1005. public clearAirRecords(id) {
  1006.  
  1007. for( new x = 0 ; x < NUM_AIR_RECORDS ; x++ )
  1008. g_fPersonalOld[id][AIR_RECORDS[x]] = 0.0
  1009.  
  1010. //Reset your AIR record variables here.
  1011. g_fIsInAir[id] = get_gametime()
  1012. g_fHeight[id] = g_fvecEndOrigin[id][2]
  1013. g_bDistCheck[id] = true
  1014. }
  1015.  
  1016. /*====================================================================================================
  1017. [Misc.]
  1018.  
  1019. Purpose: Help Clean up when round ends/player dies, or manually respawns.
  1020.  
  1021. Comment: $$
  1022.  
  1023. ====================================================================================================*/
  1024. //Client Command respawn
  1025. public cmdRespawn(id) {
  1026. new CsTeams:team = cs_get_user_team(id)
  1027. if(team == CS_TEAM_T || team == CS_TEAM_CT) {
  1028. cs_user_spawn(id)
  1029. cleanup(id)
  1030. }
  1031. return PLUGIN_HANDLED
  1032. }
  1033.  
  1034. // dead & trigger_hurt respawn
  1035. public AutoRespawn(id) {
  1036. if(is_user_connected(id)) {
  1037. cs_user_spawn(id)
  1038. cleanup(id)
  1039. if(g_bIsDead[id])
  1040. g_bIsDead[id] = false
  1041. }
  1042. }
  1043.  
  1044. public Event_ResetHUD(id) {
  1045. if(g_bIsSurf)
  1046. {
  1047. if(get_cvar_num("surf_godmode"))
  1048. entity_set_float(id,EV_FL_takedamage,0.0)
  1049. else
  1050. entity_set_float(id,EV_FL_takedamage,1.0)
  1051.  
  1052. //make sure we have a record before showing
  1053. if(is_user_connected(id) && (g_fPersonalRecord[id][SPEED] || g_fPersonalRecord[id][DISTANCE]))
  1054. showRecords(id)
  1055. }
  1056. }
  1057.  
  1058. //clean up when round ends
  1059. public Event_EndRound() {
  1060. if(g_bIsSurf) {
  1061. for(new x=1;x<=g_Maxplayers;x++)
  1062. if(is_user_connected(x))
  1063. cleanup(x)
  1064. g_EndRound = true
  1065. }
  1066. }
  1067.  
  1068. //clean up when round starts (safety)
  1069. public Event_StartRound() {
  1070. if(g_bIsSurf) {
  1071. server_print("=======|||||||||| STARTING ROUND |||||||||=========")
  1072. for(new x=1;x<=g_Maxplayers;x++)
  1073. if(is_user_connected(x)) {
  1074. if(g_bModifyMode[x]) {
  1075. menu_display(x, menu_modify[x], 0)
  1076. client_cmd(x,"slot7")
  1077. }
  1078. cleanup(x)
  1079. }
  1080. g_EndRound = false
  1081. }
  1082. }
  1083.  
  1084. public client_disconnect(id) {
  1085. if(g_bIsSurf) {
  1086. cleanup(id)
  1087. g_bIsDead[id] = false
  1088. g_bModifyMode[id] = false
  1089. g_IsFlying[id] = false
  1090.  
  1091. for( new x = 2 ; x <= NUMRECORDS ; x++ )
  1092. g_fPersonalRecord[id][x] = 0.0
  1093.  
  1094. for( new x = 1 ; x <= NUMRECORDS ; x++ ) {
  1095. g_StatText[id][x][0] = 0
  1096. g_RecordText[id][x][0] = 0
  1097. }
  1098.  
  1099. g_fPersonalRecord[id][COMPLETION] = 9999.9
  1100.  
  1101. }
  1102. }
  1103. /*====================================================================================================
  1104. [Team Control]
  1105.  
  1106. Purpose: Force Players into specified team by CVAR surf_teamstack
  1107.  
  1108. Comment: $$
  1109.  
  1110. ====================================================================================================*/
  1111. public team_select(id, key)
  1112. {
  1113. if(!g_bBothTeamsActive && g_bIsSurf) {
  1114. new teamstack = get_cvar_num("surf_teamstack")
  1115. if(teamstack == 1 || teamstack == 2)
  1116. {
  1117. if(key != 5 && key != teamstack-1)
  1118. {
  1119. new message[64]
  1120. switch(teamstack) {
  1121. case 1: format(message, 63, "You must join Terrorist team!")
  1122. case 2: format(message, 63, "You must join Counter-Terrorist team!")
  1123. }
  1124.  
  1125. message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("StatusText"), {0, 0, 0}, id);
  1126. write_byte(0);
  1127. write_string(message);
  1128. message_end();
  1129.  
  1130. engclient_cmd(id,"chooseteam")
  1131.  
  1132. return PLUGIN_HANDLED
  1133. }
  1134. }
  1135. }
  1136. return PLUGIN_CONTINUE
  1137. }
  1138.  
  1139. check_team(id,team) {
  1140. new teamstack = get_cvar_num("surf_teamstack")
  1141. //if user not in correct team, fix them
  1142. if(teamstack == 1 || teamstack == 2) {
  1143. if(team != teamstack) {
  1144. new randModel
  1145. switch(teamstack) {
  1146. case 1: randModel = random_num(1,4)
  1147. case 2: randModel = random_num(1,5)
  1148. }
  1149. select_model(id,teamstack,randModel)
  1150. }
  1151. }
  1152. }
  1153.  
  1154. public cmdSpectate(id)
  1155. select_model(id,3, 0)
  1156.  
  1157. //random model selecting for teamstack
  1158. select_model(id,team, model) {
  1159. switch(team) {
  1160. case 1: {
  1161. switch(model) {
  1162. case 1: cs_set_user_team(id, CS_TEAM_T, CS_T_TERROR)
  1163. case 2: cs_set_user_team(id, CS_TEAM_T, CS_T_LEET)
  1164. case 3: cs_set_user_team(id, CS_TEAM_T, CS_T_ARCTIC)
  1165. case 4: cs_set_user_team(id, CS_TEAM_T, CS_T_GUERILLA)
  1166. }
  1167. }
  1168. case 2: {
  1169. switch(model) {
  1170. case 1: cs_set_user_team(id, CS_TEAM_CT, CS_CT_URBAN)
  1171. case 2: cs_set_user_team(id, CS_TEAM_CT, CS_CT_GSG9)
  1172. case 3: cs_set_user_team(id, CS_TEAM_CT, CS_CT_SAS)
  1173. case 4: cs_set_user_team(id, CS_TEAM_CT, CS_CT_GIGN)
  1174. case 5: cs_set_user_team(id, CS_TEAM_CT, CS_CT_VIP) //my lil secret
  1175. }
  1176. }
  1177. case 3: {
  1178. cs_set_user_team(id, CS_TEAM_SPECTATOR, CS_DONTCHANGE)
  1179. if(is_user_alive(id))
  1180. user_kill(id)
  1181. }
  1182. }
  1183. }
  1184.  
  1185. public client_command(id) {
  1186. if(g_bIsSurf && get_cvar_num("surf_teamstack") > 0) {
  1187. new arg[64]
  1188. read_argv( 0, arg , 63 )
  1189. if( equal("chooseteam",arg) || equal("jointeam",arg) ) {
  1190. return PLUGIN_HANDLED
  1191. }
  1192. }
  1193. return PLUGIN_CONTINUE
  1194. }
  1195. /*====================================================================================================
  1196. [Remove Weapons]
  1197.  
  1198. Purpose: Remove the weapon listed in game_player_equip entity, (since this will be the most dropped).
  1199.  
  1200. Comment: Thanks to BAILOPAN on this safe weapon removal method.
  1201.  
  1202. ====================================================================================================*/
  1203. public Event_DeathMsg()
  1204. {
  1205. if(g_bIsSurf) {
  1206. new player = read_data(2)
  1207. if(player) {
  1208. new wps[32], num, i, Drop[1]
  1209. get_user_weapons(player, wps, num) //catch every dropped weapon!
  1210.  
  1211. for (i=0; i<num; i++) {
  1212. Drop[0] = wps[i]
  1213. set_task(0.2,"remove_weapon", 0, Drop, 1)
  1214. }
  1215. }
  1216. }
  1217. }
  1218.  
  1219. public remove_weapon(data[])
  1220. {
  1221. new wp = data[0]
  1222. new weapbox, model[64], left[32], right[32]
  1223.  
  1224. while((weapbox = find_ent_by_class(weapbox,"weaponbox")) != 0)
  1225. {
  1226. entity_get_string(weapbox,EV_SZ_model,model,63)
  1227. for(new x = 0; x < g_TotalWeap ; x++)
  1228. {
  1229. strtok(g_StartWeap[x], left, 31, right, 32, '_')
  1230. if( containi(model, right) != -1 )
  1231. remove_weapon_final(wp, weapbox)
  1232. }
  1233. }
  1234.  
  1235. }
  1236.  
  1237. remove_weapon_final(wp, weapbox) {
  1238. new wEnt, wfEnt, name[24]
  1239. new woEnt
  1240.  
  1241. remove_entity(weapbox)
  1242. get_weaponname(wp, name, 24)
  1243. wEnt = find_ent_by_class(-1, name)
  1244. while (wEnt > 0) {
  1245. wfEnt = find_ent_by_class(wEnt, name)
  1246. woEnt = entity_get_edict(wEnt, EV_ENT_owner)
  1247. if (woEnt > 32 && woEnt == weapbox)
  1248. remove_entity(wEnt)
  1249.  
  1250. wEnt = wfEnt
  1251. }
  1252. }
  1253. /*====================================================================================================
  1254. [nVault Data Handling]
  1255.  
  1256. Purpose: Saves/Loads EndZone Location origin to file. Also save record, saves to vault and cascades
  1257. records down a rank. LoadRecord is called once at map load, to load records saved in vault.
  1258. RecordLookup is called when player types /top3 and formats it to fit on MOTD window.
  1259.  
  1260. Comment: $$
  1261.  
  1262. ====================================================================================================*/
  1263. SaveEndZoneLocation(Float:ezOrig[3]) {
  1264.  
  1265. Vault_EndZone = nvault_open( ENDZONE_VAULT )
  1266. if(Vault_EndZone == INVALID_HANDLE)
  1267. server_print("Error opening nVault file: %s",ENDZONE_VAULT)
  1268.  
  1269. new key[64], update[511]
  1270.  
  1271. format(key,63,"%s",g_MapName)
  1272. format(update,510,"^"%f^" ^"%f^" ^"%f^"",ezOrig[0],ezOrig[1],ezOrig[2])
  1273.  
  1274. if(ezOrig[0] != 0.0 && ezOrig[1] != 0.0 && ezOrig[2] != 0.0) {
  1275. if(!g_EndzoneEntity)
  1276. createEndZone()
  1277.  
  1278. entity_set_origin(g_EndzoneEntity,ezOrig)
  1279. }
  1280. nvault_set(Vault_EndZone, key, update) //update End Zone Location
  1281.  
  1282. nvault_close(Vault_EndZone)
  1283.  
  1284. for( new x = 1 ; x <= NUMRANKS ; x++ )
  1285. saveRecord("0", "Nobody", x, COMPLETION, 9999.9)
  1286.  
  1287. for( new x = 1 ; x <= g_Maxplayers ; x++ )
  1288. g_fPersonalRecord[x][COMPLETION] = 9999.0
  1289. }
  1290.  
  1291. LoadEndZoneLocation() {
  1292.  
  1293. Vault_EndZone = nvault_open( ENDZONE_VAULT )
  1294. if(Vault_EndZone == INVALID_HANDLE)
  1295. server_print("Error opening nVault file: %s",ENDZONE_VAULT)
  1296.  
  1297. new key[64], val[511], TimeStamp
  1298. new endzoneOrig[3][64]
  1299.  
  1300. format(key,63,"%s",g_MapName)
  1301.  
  1302. //Retrieve origin from file, parse it, convert to float, and set it to endzone model.
  1303. if( nvault_lookup(Vault_EndZone, key, val, 510, TimeStamp) ) {
  1304. parse(val, endzoneOrig[0], 63, endzoneOrig[1], 63, endzoneOrig[2], 63)
  1305. new Float:ezOrig[3]
  1306. for(new x=0;x<3;x++)
  1307. ezOrig[x] = floatstr(endzoneOrig[x])
  1308.  
  1309. if(ezOrig[0] != 0 && ezOrig[1] != 0 && ezOrig[2] != 0)
  1310. createEndZone()
  1311.  
  1312. if(g_EndzoneEntity)
  1313. entity_set_origin(g_EndzoneEntity,ezOrig)
  1314. nvault_close(Vault_EndZone)
  1315. }
  1316. else
  1317. nvault_close(Vault_EndZone)
  1318. }
  1319.  
  1320. saveRecord(authid[], name[], rank, recordtype, Float:record) {
  1321.  
  1322. Vault = nvault_open( VAULTNAME )
  1323. if(Vault == INVALID_HANDLE)
  1324. server_print("Error opening nVault file: %s",VAULTNAME)
  1325.  
  1326. new key[64], update[511]
  1327.  
  1328. format(key,63,"%s %i %i",g_MapName,rank,recordtype)
  1329. format(update,510,"^"%s^" ^"%s^" ^"%f^"", authid, name, record)
  1330.  
  1331. format(g_TopRecordSteamId[recordtype][rank],MAX_TEXT_LENGTH,"%s",authid) //steamid
  1332. format(g_TopRecordName[recordtype][rank],MAX_TEXT_LENGTH,"%s",name) //name
  1333.  
  1334. g_fTopRecord[recordtype][rank] = record
  1335.  
  1336. nvault_set(Vault, key, update)
  1337.  
  1338. nvault_close(Vault)
  1339. }
  1340.  
  1341. LoadRecords() {
  1342.  
  1343. Vault = nvault_open( VAULTNAME )
  1344.  
  1345. if(Vault == INVALID_HANDLE)
  1346. server_print("Error opening nVault file: %s",VAULTNAME)
  1347.  
  1348. new key[64], value[511], TimeStamp
  1349. new playerinfo[3][MAX_TEXT_LENGTH+1] // "STEAMID" "NICK" "RECORD"
  1350. new empty[511], full[511] //full is for completion to == 9999.0
  1351.  
  1352. format(full,510,"^"0^" ^"Nobody^" ^"9999.0^"")
  1353. format(empty,510,"^"0^" ^"Nobody^" ^"0.0^"")
  1354.  
  1355. for( new x = 1 ; x <= NUMRECORDS ; x++ ) {
  1356. for( new m = 1 ; m <= NUMRANKS ; m++ )
  1357. {
  1358. format(key,63,"%s %i %i",g_MapName,m,x)
  1359. if( nvault_lookup(Vault, key, value, 510, TimeStamp) ) {
  1360.  
  1361. parse(value, playerinfo[0], MAX_TEXT_LENGTH, playerinfo[1], MAX_TEXT_LENGTH, playerinfo[2], MAX_TEXT_LENGTH)
  1362.  
  1363. g_fTopRecord[x][m] = floatstr(playerinfo[2])
  1364. format(g_TopRecordSteamId[x][m],MAX_TEXT_LENGTH,"%s",playerinfo[0]) //steamid
  1365. format(g_TopRecordName[x][m],MAX_TEXT_LENGTH,"%s",playerinfo[1]) //name
  1366. }
  1367. else { //Fill empty slots
  1368. if(x == COMPLETION)
  1369. nvault_set(Vault, key, full) //Fill in None and 9999.0
  1370. else
  1371. nvault_set(Vault, key, empty) //Fill in None and 0.0
  1372. format(g_TopRecordSteamId[x][m],MAX_TEXT_LENGTH,"0") //steamid
  1373. format(g_TopRecordName[x][m],MAX_TEXT_LENGTH,"Nobody") //name
  1374. }
  1375. }
  1376. }
  1377. nvault_close(Vault)
  1378. }
  1379.  
  1380. public recordLookUp(id) {
  1381.  
  1382. Vault = nvault_open( VAULTNAME )
  1383. if(Vault == INVALID_HANDLE)
  1384. server_print("Error opening nVault file: %s",VAULTNAME)
  1385.  
  1386. new key[64], value[511], TimeStamp
  1387. new rankings[MAX_BUFFER_LENGTH+1], map[64]
  1388. new Float:record
  1389. new playerinfo[3][MAX_TEXT_LENGTH+1] // "STEAMID" "NICK" "RECORD"
  1390.  
  1391. new rLen = 0
  1392.  
  1393. format(map,63,"Top Records: %s ",g_MapName)
  1394. rLen += format(rankings,MAX_BUFFER_LENGTH,"<body bgcolor=#000000><font color=#FFB000><br>")
  1395.  
  1396. //Write personal record statistics
  1397. rLen += format(rankings[rLen],MAX_BUFFER_LENGTH-rLen,"<p><b>Personal Statistics</b><br>")
  1398. for( new x = 1 ; x <= NUMRECORDS ; x++ )
  1399. {
  1400. if( x == COMPLETION && !g_EndzoneEntity ) continue //No EndZone, skip completions!
  1401. rLen += format(rankings[rLen],MAX_BUFFER_LENGTH-rLen,"%s: %.2f %s<br>",TITLES[x],g_fPersonalRecord[id][x],TYPES[x])
  1402. }
  1403. rLen += format(rankings[rLen],MAX_BUFFER_LENGTH-rLen,"</p>")
  1404.  
  1405. //Write top record statistics
  1406. for( new x = 1 ; x <= NUMRECORDS ; x++ )
  1407. {
  1408. if( x == COMPLETION && !g_EndzoneEntity ) continue //No EndZone, skip completions!
  1409.  
  1410. rLen += format(rankings[rLen],MAX_BUFFER_LENGTH-rLen,"<p><b>Record %s</b><br>",TITLES[x])
  1411.  
  1412. for( new m = 1 ; m <= NUMRANKS ; m++ )
  1413. {
  1414. format(key,63,"%s %i %i",g_MapName,m,x)
  1415. if( nvault_lookup(Vault, key, value, 510, TimeStamp) )
  1416. {
  1417. parse(value, playerinfo[0], MAX_TEXT_LENGTH, playerinfo[1], MAX_TEXT_LENGTH, playerinfo[2], MAX_TEXT_LENGTH)
  1418. record = floatstr(playerinfo[2])
  1419.  
  1420. rLen += format(rankings[rLen],MAX_BUFFER_LENGTH-rLen,"%i%s : %s %.2f %s<br>",m,RANKS[m],playerinfo[1],record,TYPES[x])
  1421. }
  1422. }
  1423. rLen += format(rankings[rLen],MAX_BUFFER_LENGTH-rLen,"</p>")
  1424. }
  1425. nvault_close(Vault)
  1426. show_motd(id,rankings,map)
  1427. }
  1428.  
  1429. /*====================================================================================================
  1430. [Keyvalue]
  1431.  
  1432. Purpose: Since this runs before plugin_precache and plugin_init, find out if it's a surf map here.
  1433. Then disable all damage from trigger_hurts and func_water, disable kill buttons.
  1434. Also save target/targetname and id's of trigger_teleport, info_teleport_destination, and
  1435. info_target.
  1436.  
  1437. Comment: This function runs whenever something spawns, but for these entities,
  1438. it is used only at map load.
  1439.  
  1440. ==================================================================================================*/
  1441. public pfn_keyvalue(entid) {
  1442. if(!g_bRunOnce) {
  1443. get_mapname(g_MapName,64)
  1444. if(containi(g_MapName, "surf") != -1 || containi(g_MapName, "wurf") != -1)
  1445. g_bIsSurf = true
  1446. else
  1447. g_bIsSurf = false
  1448. g_bRunOnce = true
  1449. }
  1450. if(g_bIsSurf) {
  1451. new classname[32], key[32], value[32]
  1452. copy_keyvalue(classname, 31, key, 31, value, 31)
  1453.  
  1454. if(equal(classname,"env_explosion"))
  1455. remove_entity(entid)
  1456.  
  1457. /***** Remove damage from entities *****/
  1458. if(equal(classname,"func_water"))
  1459. if(equal(key,"lip"))
  1460. DispatchKeyValue("lip","0")
  1461.  
  1462. if(equal(key, "dmg"))
  1463. if(floatstr(value) > 0.0) //Only cancel damage, some trigger_hurts give HP
  1464. DispatchKeyValue("dmg","0")
  1465.  
  1466. if(equal(key, "damagetype"))
  1467. DispatchKeyValue("damagetype","0")
  1468. /***************************************/
  1469.  
  1470. /*********** trigger_hurt healers **********/
  1471. if(equali(classname,"trigger_hurt"))
  1472. if(equali(key,"dmg"))
  1473. if(floatstr(value) < 0.0)
  1474. g_TriggerHurtHealers[g_TrigHurtHealTotal++] = entid
  1475. /*******************************************/
  1476.  
  1477. /******* Player Equip Weapon Info ******/
  1478. if( (equali(classname,"game_player_equip")) && (containi(key,"weapon_") != -1) && (!equali(key,"weapon_knife")) )
  1479. format(g_StartWeap[g_TotalWeap++],63,"%s",key)
  1480. /***************************************/
  1481.  
  1482. /************* Player Spawn Info *******/
  1483. if(equal(classname, "info_player_start"))
  1484. g_InfoPlayerStart++
  1485.  
  1486. if(equal(classname, "info_player_deathmatch"))
  1487. g_InfoPlayerDeathmatch++
  1488. /***************************************/
  1489.  
  1490. /*********** Teleport Info *************/
  1491. if(equal(classname, "info_teleport_destination") || equal(classname, "info_target") || equal(classname, "trigger_teleport"))
  1492. if(equal(key, "targetname")) { //save "targetname" to link to target and save ID
  1493. format(g_TeleDest[g_TotalTeleDest],31,"%s",value)
  1494. g_TeleDestId[g_TotalTeleDest++] = entid
  1495. }
  1496. if(equal(classname, "trigger_teleport")) {
  1497. if(equal(key, "target")) { //save "target" to link to targetname and save ID
  1498. format(g_TriggerTeleport[g_TotalTeleports],31,"%s",value)
  1499. g_TriggerTeleId[g_TotalTeleports++] = entid
  1500. }
  1501. }
  1502. /***************************************/
  1503. }
  1504. }
  1505.  
  1506. /*====================================================================================================
  1507. [EndZone Tool & Other Menus Setup]
  1508.  
  1509. Purpose: Link our target/targetnames into one array and save id's of linked trigger_teleport/destinations.
  1510. After that, create our EndZone entity, with a bounding box. Search if map has a saved origin
  1511. for it and apply, if not don't create entity. Finally create several of our menus automatically
  1512. based on information we have.
  1513.  
  1514. Comment: This is done on mapload, and never again.
  1515.  
  1516. =====================================================================================================*/
  1517. LoadMenus() {
  1518.  
  1519. new targetName[100][32] //Save the target name for tele menu
  1520.  
  1521. //Link teleport <-> destination
  1522. for(new x=0;x<g_TotalTeleDest;x++)
  1523. for(new m=0;m<g_TotalTeleports;m++)
  1524. if(equal(g_TriggerTeleport[m], g_TeleDest[x])) { //if target & targetname are the same, put both ID's in our array
  1525. g_LinkedTeleAndDest[g_TotalLinked][0] = g_TriggerTeleId[m]
  1526. g_LinkedTeleAndDest[g_TotalLinked][1] = g_TeleDestId[x]
  1527. format(targetName[g_TotalLinked++],31,g_TeleDest[x])
  1528. }
  1529.  
  1530. for(new x=1;x<=g_Maxplayers;x++)
  1531. g_fPersonalRecord[x][COMPLETION] = 9999.0 //Set default user completions to 9999.0
  1532.  
  1533. for(new x=1;x<=NUMRANKS;x++)
  1534. g_fTopRecord[COMPLETION][x] = 9999.0 //Set default top completions to 9999.0
  1535.  
  1536.  
  1537. /**************** EndZone Entity Box *****************************/
  1538. LoadEndZoneLocation()
  1539. /*************************************************************/
  1540.  
  1541.  
  1542. /****************** Automated Menu Creation ***********************/
  1543. //End Zone Menu
  1544. for(new x=1;x<g_Maxplayers;x++) {
  1545. menu_modify[x] = menu_create("EndZone Creation Tool:", "Endzone_Handler");
  1546. if(!g_EndzoneEntity)
  1547. menu_additem(menu_modify[x], "Create EndZone Here", "1", ADMIN_RCON)
  1548. else
  1549. menu_additem(menu_modify[x], "Move EndZone Here", "1", ADMIN_RCON)
  1550. menu_additem(menu_modify[x], "NoClip (OFF)","2", ADMIN_RCON)
  1551. menu_additem(menu_modify[x], "Flying (OFF)","3", ADMIN_RCON)
  1552. menu_additem(menu_modify[x], "Choose Teleport Destination", "4", ADMIN_RCON)
  1553. menu_addblank(menu_modify[x], 5)
  1554. menu_additem(menu_modify[x], "Go to current EndZone", "6", ADMIN_RCON)
  1555. menu_additem(menu_modify[x], "Delete EndZone", "7", ADMIN_RCON)
  1556. menu_addblank(menu_modify[x], 8)
  1557. menu_setprop(menu_modify[x], MPROP_EXIT, MEXIT_ALL);
  1558. }
  1559.  
  1560. //Delete Records Menu
  1561. new num[11]
  1562. menu_deleterecords = menu_create("Delete Records Menu:", "DeleteRecord_Handler")
  1563. menu_additem(menu_deleterecords, "All Records", "0", ADMIN_RCON)
  1564. for( new x = 1 ; x <= NUMRECORDS ; x++ ) {
  1565. format(num,10,"%i",x)
  1566. menu_additem(menu_deleterecords, TITLES[x], num, ADMIN_RCON)
  1567. }
  1568. menu_addblank(menu_deleterecords, NUMRECORDS+1)
  1569. menu_setprop(menu_deleterecords, MPROP_EXIT, MEXIT_ALL);
  1570.  
  1571.  
  1572. //Teleport Menu
  1573. menu_teleport = menu_create("Choose Teleport Destination:", "Teleport_Handler");
  1574. menu_additem(menu_teleport, "Previous Location", "1")
  1575.  
  1576. new menu_name[64], menu_cmd[64]
  1577. for(new x=0;x<g_TotalLinked;x++) {
  1578. //if duplicate move on
  1579. if(equal(targetName[x],"@@@@@@@")) continue
  1580.  
  1581. //create menu item
  1582. format(menu_name,63,"Tele (%s)",targetName[x])
  1583. format(menu_cmd,63,"%i",g_LinkedTeleAndDest[x][0])
  1584. menu_additem(menu_teleport, menu_name, menu_cmd, ADMIN_RCON);
  1585.  
  1586. //delete duplicate destinations (mark w/ @@@@@@@)
  1587. for(new m=x+1;m<g_TotalLinked;m++)
  1588. if(equal(targetName[x], targetName[m]))
  1589. format(targetName[m],31,"@@@@@@@")
  1590. }
  1591. menu_setprop(menu_teleport, MPROP_PERPAGE, 6);
  1592. menu_setprop(menu_teleport, MPROP_EXIT, MEXIT_ALL);
  1593. menu_setprop(menu_teleport, MPROP_NEXTNAME, "More");
  1594.  
  1595. //Help Menu
  1596. menu_help = menu_create("Help FAQ Information:", "Help_Handler");
  1597. menu_additem(menu_help, "How to Surf?", "1", 0)
  1598. menu_additem(menu_help, "How to view top records?","2", 0)
  1599. menu_additem(menu_help, "Restart Completion Time or Stuck?", "3", 0)
  1600. menu_additem(menu_help, "How do I play Surf_Olymipcs?", "4", 0)
  1601. menu_additem(menu_help, "About plugin.", "5", 0)
  1602. menu_addblank(menu_help, 6)
  1603. menu_setprop(menu_help, MPROP_EXIT, MEXIT_ALL);
  1604.  
  1605. menu_savecheck = menu_create("(Saving Location) Are you sure?", "Save_Handler");
  1606. menu_additem(menu_savecheck, "YES", "1", ADMIN_RCON)
  1607. menu_additem(menu_savecheck, "CANCEL", "5", ADMIN_RCON)
  1608. menu_setprop(menu_savecheck, MPROP_EXIT, MEXIT_NEVER);
  1609.  
  1610. menu_deletecheck = menu_create("(Deleting EndZone) Are you sure?", "Delete_Handler");
  1611. menu_additem(menu_deletecheck, "YES", "1", ADMIN_RCON)
  1612. menu_additem(menu_deletecheck, "CANCEL", "5", ADMIN_RCON)
  1613. menu_setprop(menu_deletecheck, MPROP_EXIT, MEXIT_NEVER);
  1614. /*******************************************************************/
  1615. }
  1616.  
  1617. /*====================================================================================================
  1618. [Enable/Disable Surf_Olympics]
  1619.  
  1620. Purpose: Enable/Disable surf olympic plugin completely, minus /respawn, /spec, /top3 .
  1621. COMMAND: surf_on <1|0>
  1622.  
  1623. Comment: $$
  1624.  
  1625. ====================================================================================================*/
  1626. public cmdEnable(id,level,cid) {
  1627. if (!cmd_access(id,level,cid,1))
  1628. return PLUGIN_HANDLED
  1629. new arg[32], status
  1630. read_argv(1,arg,31)
  1631. status = str_to_num(arg)
  1632. if(status == 1) {
  1633. set_cvar_num(TITLE,1)
  1634. g_bIsSurf = true
  1635. client_print(0,print_chat,"[Surf Olympics] Plugin is now enabled.")
  1636. new team
  1637. for(new id=1;id<=g_Maxplayers;id++) {
  1638. team = get_user_team(id)
  1639. if(is_user_connected(id) && (team == 1 || team == 2))
  1640. AutoRespawn(id)
  1641. }
  1642. }
  1643. else {
  1644. set_cvar_num(TITLE,0)
  1645. g_bIsSurf = false
  1646. client_print(0,print_chat,"[Surf Olympics] Plugin is now disabled.")
  1647. }
  1648. return PLUGIN_HANDLED
  1649. }
  1650.  
  1651. /*====================================================================================================
  1652. [Delete Record Menu]
  1653.  
  1654. Purpose: Opens a menu for deleting ALL records or by Record Type.
  1655. COMMAND: surf_delete
  1656.  
  1657. Comment: $$
  1658.  
  1659. ====================================================================================================*/
  1660. public cmdDeleteRecords(id, level, cid)
  1661. {
  1662. if( g_bIsSurf && (id > 0) && (id <= g_Maxplayers) && is_user_connected(id) && cmd_access(id,level,cid,0))
  1663. menu_display(id, menu_deleterecords, 0)
  1664.  
  1665. return PLUGIN_HANDLED
  1666. }
  1667.  
  1668. public DeleteRecord_Handler(id, menu, item)
  1669. {
  1670. if(is_user_connected(id)) {
  1671. if(item == MENU_EXIT || !g_bIsSurf) {
  1672. return PLUGIN_HANDLED
  1673. }
  1674.  
  1675. new cmd[6], iName[64];
  1676. new access, callback;
  1677. menu_item_getinfo(menu, item, access, cmd,5, iName, 63, callback);
  1678.  
  1679. new recordtype = str_to_num(cmd)
  1680.  
  1681. new delRecord[MAX_TEXT_LENGTH+1]
  1682. if(recordtype != 0)
  1683. format(delRecord,MAX_TEXT_LENGTH,"(Deleting %s Records) Are you sure?",TITLES[recordtype])
  1684. else
  1685. format(delRecord,MAX_TEXT_LENGTH,"(Deleting ALL Records) Are you sure?")
  1686.  
  1687. new menu_areyousure = menu_create(delRecord, "DelCheck_Handler")
  1688. menu_additem(menu_areyousure, "YES", cmd, ADMIN_RCON)
  1689. menu_additem(menu_areyousure, "CANCEL", "500", ADMIN_RCON)
  1690. menu_setprop(menu_areyousure, MPROP_EXIT, MEXIT_NEVER);
  1691.  
  1692. menu_display(id, menu_areyousure, 0)
  1693. }
  1694. return PLUGIN_HANDLED
  1695. }
  1696.  
  1697. public DelCheck_Handler(id, menu, item)
  1698. {
  1699. if(is_user_connected(id))
  1700. {
  1701. new cmd[6], iName[64];
  1702. new access, callback;
  1703. menu_item_getinfo(menu, item, access, cmd,5, iName, 63, callback);
  1704.  
  1705. new recordtype = str_to_num(cmd)
  1706. new Float:record
  1707.  
  1708. if(recordtype == 0) //All Records
  1709. {
  1710. for( new m = 1 ; m <= NUMRECORDS ; m++ )
  1711. {
  1712. if(m == COMPLETION)
  1713. record = 9999.9
  1714. else
  1715. record = 0.0
  1716.  
  1717. for(new x=1;x<=NUMRANKS;x++)
  1718. saveRecord("0", "Nobody", x, m, record)
  1719. }
  1720. }
  1721. else if(recordtype != 500) //Single Record Type
  1722. {
  1723. if(recordtype == COMPLETION)
  1724. record = 9999.9
  1725.  
  1726. for( new x = 1 ; x <= NUMRANKS ; x++ )
  1727. saveRecord("0", "Nobody", x, recordtype, record)
  1728. }
  1729. }
  1730. }
  1731.  
  1732. /*====================================================================================================
  1733. [EndZone Creation Tool]
  1734.  
  1735. Purpose: surf_endzone admin command. This handles all the EndZone Tool features.
  1736. COMMAND: surf_endzone
  1737.  
  1738. Comment: I tried making it flexible for the average user. Even allows some cool combos.
  1739.  
  1740. ====================================================================================================*/
  1741. public cmdEZModify(id,level,cid) {
  1742. if(!g_bIsSurf) {
  1743. client_print(id,print_chat,"[Surf Olympics] ERROR: Surf Olympics must be activated to use this tool.")
  1744. return PLUGIN_HANDLED
  1745. }
  1746. if(!id) {
  1747. server_print("[Surf Olympics] ERROR: surf_endzone is a command for ingame use only.")
  1748. return PLUGIN_HANDLED
  1749. }
  1750.  
  1751. new CsTeams:team = cs_get_user_team(id)//get_user_team(id)
  1752. if (!cmd_access(id,level,cid,0) || g_EndRound || !is_user_alive(id) || (team != CS_TEAM_T && team != CS_TEAM_CT))
  1753. return PLUGIN_HANDLED
  1754.  
  1755. g_bModifyMode[id] = true
  1756. entity_set_float(id,EV_FL_takedamage,0.0)
  1757. if(!g_EndzoneEntity) {
  1758. menu_item_setname(menu_modify[id],5, "(NULL) Delete EndZone")
  1759. menu_item_setname(menu_modify[id],0, "Create EndZone Here")
  1760. }
  1761. else {
  1762. menu_item_setname(menu_modify[id],5, "Delete EndZone")
  1763. menu_item_setname(menu_modify[id],0, "Move EndZone Here")
  1764. }
  1765. menu_item_setname(menu_modify[id],1, "NoClip (OFF)")
  1766. menu_item_setname(menu_modify[id], 2, "Flying (OFF)")
  1767. menu_display(id, menu_modify[id], 0)
  1768. return PLUGIN_HANDLED
  1769. }
  1770.  
  1771. public Endzone_Handler(id, menu, item) {
  1772. if(is_user_connected(id)) {
  1773. if(item == MENU_EXIT || !g_bIsSurf) {
  1774. g_IsFlying[id] = false
  1775. g_bModifyMode[id] = false
  1776. AutoRespawn(id)
  1777. return PLUGIN_HANDLED
  1778. }
  1779. switch(item) {
  1780. case 0: //save loc to file
  1781. {
  1782. menu_display(id, menu_savecheck, 0)
  1783. return PLUGIN_HANDLED
  1784. }
  1785. case 1: //noclip on/off (cancel out flying)
  1786. {
  1787. new movetype = entity_get_int(id, EV_INT_movetype)
  1788. switch(movetype) {
  1789. case MOVETYPE_NOCLIP: {
  1790. entity_set_int(id, EV_INT_movetype, MOVETYPE_WALK)
  1791. menu_item_setname(menu, item, "NoClip (OFF)")
  1792. }
  1793. case MOVETYPE_WALK: {
  1794. entity_set_int(id, EV_INT_movetype, MOVETYPE_NOCLIP)
  1795.  
  1796. menu_item_setname(menu, item, "NoClip (ON)")
  1797. menu_item_setname(menu, item+1, "Flying (OFF)")
  1798. g_IsFlying[id] = false
  1799. }
  1800. }
  1801. }
  1802. case 2: //flying on/off (cancel out noclip)
  1803. {
  1804. if(!g_IsFlying[id]) {
  1805. g_IsFlying[id] = true
  1806. menu_item_setname(menu, item-1, "NoClip (OFF)")
  1807. menu_item_setname(menu, item, "Flying (ON)")
  1808. entity_set_int(id, EV_INT_movetype, MOVETYPE_WALK)
  1809. }
  1810. else {
  1811. g_IsFlying[id] = false
  1812. menu_item_setname(menu, item, "Flying (OFF)")
  1813. }
  1814. }
  1815. case 3: //teleport menu
  1816. {
  1817. menu_display(id, menu_teleport, 0)
  1818. return PLUGIN_HANDLED
  1819. }
  1820. case 4: //go to endzone location
  1821. {
  1822. if(!g_EndzoneEntity)
  1823. client_print(id,print_chat,"[Surf Olympics] - There is no EndZone created yet!")
  1824. else {
  1825. new Float:ezEntOrig[3]
  1826. entity_get_vector(g_EndzoneEntity,EV_VEC_origin,ezEntOrig)
  1827. entity_set_origin(id,ezEntOrig)
  1828. new Float:temp_vel[3]
  1829. entity_set_vector(id,EV_VEC_velocity,temp_vel)
  1830. }
  1831. }
  1832. case 5:
  1833. {
  1834. if(!g_EndzoneEntity)
  1835. client_print(id,print_chat,"[Surf Olympics] - There is no EndZone to delete!")
  1836. else {
  1837. menu_display(id, menu_deletecheck, 0)
  1838. return PLUGIN_HANDLED
  1839. }
  1840. }
  1841. }
  1842. if(item != MENU_EXIT && item != MENU_BACK && item != MENU_MORE)
  1843. menu_display(id, menu_modify[id], 0)
  1844. }
  1845. return PLUGIN_HANDLED
  1846. }
  1847.  
  1848. public Delete_Handler(id, menu, item) {
  1849. if(is_user_connected(id)) {
  1850. if(item == 0 )
  1851. {
  1852. remove_entity(g_EndzoneEntity)
  1853. g_EndzoneEntity = 0
  1854. new Float:nullOrig[3]
  1855. SaveEndZoneLocation(nullOrig)
  1856. menu_item_setname(menu_modify[id],5, "(NULL) Delete EndZone")
  1857. menu_item_setname(menu_modify[id],0, "Create EndZone Here")
  1858. }
  1859. menu_display(id,menu_modify[id], 0)
  1860. }
  1861. return PLUGIN_HANDLED
  1862. }
  1863.  
  1864. public Save_Handler(id, menu, item) {
  1865. if(is_user_connected(id)) {
  1866. if(item == 0)
  1867. {
  1868. new Float:myorig[3]
  1869. entity_get_vector(id,EV_VEC_origin,myorig)
  1870. menu_item_setname(menu_modify[id],5, "Delete EndZone")
  1871. menu_item_setname(menu_modify[id],0, "Move EndZone Here")
  1872. SaveEndZoneLocation(myorig)
  1873. }
  1874. menu_display(id,menu_modify[id], 0)
  1875. }
  1876. return PLUGIN_HANDLED
  1877. }
  1878.  
  1879. public Teleport_Handler(id, menu, item) {
  1880. if(is_user_connected(id)) {
  1881. if(item == MENU_EXIT) {
  1882. menu_display(id, menu_modify[id], 0)
  1883. return PLUGIN_HANDLED
  1884. }
  1885. new cmd[6], iName[64];
  1886. new access, callback;
  1887. menu_item_getinfo(menu, item, access, cmd,5, iName, 63, callback);
  1888.  
  1889. //If user teleports by accident, this allows them to return to their location.
  1890. if(item > -1) {
  1891. if(str_to_num(cmd) == 1) {
  1892. if(g_fvecPrevOrigin[id][0] == 0.0 && g_fvecPrevOrigin[id][1] == 0.0 && g_fvecPrevOrigin[id][2] == 0.0) {
  1893. menu_display(id, menu_modify[id], 0)
  1894. return PLUGIN_HANDLED
  1895. }
  1896. //setting origin doesn't remove users velocity, so do it for them.
  1897. new Float:temp_vel[3]
  1898. entity_set_vector(id,EV_VEC_velocity,temp_vel)
  1899. entity_set_origin(id,g_fvecPrevOrigin[id])
  1900. menu_display(id, menu_modify[id], 0)
  1901. return PLUGIN_HANDLED
  1902. }
  1903.  
  1904. new teleport_id = str_to_num(cmd)
  1905.  
  1906. entity_get_vector(id,EV_VEC_origin,g_fvecPrevOrigin[id]) //Save location to go back (Previous Location)
  1907.  
  1908. fake_touch(teleport_id,id) //fake touch chosen teleport
  1909.  
  1910. menu_display(id, menu_modify[id], 0)
  1911. }
  1912. }
  1913. return PLUGIN_HANDLED
  1914. }
  1915.  
  1916. /*====================================================================================================
  1917. [Fly Mode]
  1918.  
  1919. Purpose: The ability to fly allows the ADMIN to create EndZone locations much faster and easier.
  1920.  
  1921. Comment: This was created by Gorlag/Batman. FULL CREDIT to him for this Flying mode.
  1922.  
  1923. =====================================================================================================*/
  1924. public client_PreThink(id)
  1925. {
  1926. if( g_bIsSurf && g_IsFlying[id] )
  1927. define_flyMovements(id)
  1928. }
  1929.  
  1930. public define_flyMovements(id)
  1931. {
  1932. new maxSpeed = get_cvar_num("surf_flyspeed")
  1933. new Float:fVelocity[3], Float:v_angles[3]
  1934. new flag = entity_get_int(id, EV_INT_flags)
  1935. new buttonPressed = entity_get_int(id, EV_INT_button)
  1936. if(flag & FL_ONGROUND){
  1937. if(buttonPressed & IN_JUMP){
  1938. entity_get_vector(id, EV_VEC_velocity, fVelocity)
  1939. fVelocity[2] += 8000.0
  1940. entity_set_vector(id, EV_VEC_velocity, fVelocity)
  1941. }
  1942. }
  1943. if(!(flag & FL_ONGROUND)) {
  1944. if((buttonPressed & IN_FORWARD) && !(buttonPressed & IN_BACK) && !(buttonPressed & IN_MOVELEFT) && !(buttonPressed & IN_MOVERIGHT)){
  1945. velocity_by_aim(id, maxSpeed, fVelocity)
  1946. entity_set_vector(id, EV_VEC_velocity, fVelocity)
  1947. }
  1948. if((buttonPressed & IN_BACK) && !(buttonPressed & IN_FORWARD) && !(buttonPressed & IN_MOVELEFT) && !(buttonPressed & IN_MOVERIGHT)){
  1949. velocity_by_aim(id, maxSpeed, fVelocity)
  1950. fVelocity[0] -= fVelocity[0]*2.0
  1951. fVelocity[1] -= fVelocity[1]*2.0
  1952. fVelocity[2] -= fVelocity[2]*2.0
  1953. entity_set_vector(id, EV_VEC_velocity, fVelocity)
  1954. }
  1955. if((buttonPressed & IN_MOVELEFT) && !(buttonPressed & IN_FORWARD) && !(buttonPressed & IN_MOVERIGHT) && !(buttonPressed & IN_BACK)){
  1956. entity_get_vector(id, EV_VEC_v_angle, v_angles)
  1957. v_angles[1] += 90.0
  1958. fVelocity[0] = floatcos(v_angles[1], degrees) * maxSpeed
  1959. fVelocity[1] = floatsin(v_angles[1], degrees) * maxSpeed
  1960. fVelocity[2] = 0.0
  1961. entity_set_vector(id, EV_VEC_velocity, fVelocity)
  1962. }
  1963. if((buttonPressed & IN_MOVERIGHT) && !(buttonPressed & IN_FORWARD) && !(buttonPressed & IN_BACK) && !(buttonPressed & IN_MOVELEFT)){
  1964. entity_get_vector(id, EV_VEC_v_angle, v_angles)
  1965. v_angles[1] += 270.0
  1966. fVelocity[0] = floatcos(v_angles[1], degrees) * maxSpeed
  1967. fVelocity[1] = floatsin(v_angles[1], degrees) * maxSpeed
  1968. fVelocity[2] = 0.0
  1969. entity_set_vector(id, EV_VEC_velocity, fVelocity)
  1970. }
  1971. if((buttonPressed & IN_FORWARD) && (buttonPressed & IN_MOVELEFT) && !(buttonPressed & IN_MOVERIGHT) && !(buttonPressed & IN_BACK)){
  1972. entity_get_vector(id, EV_VEC_v_angle, v_angles)
  1973. v_angles[1] += 45.0
  1974. fVelocity[0] = floatcos(v_angles[1], degrees) * maxSpeed
  1975. fVelocity[1] = floatsin(v_angles[1], degrees) * maxSpeed
  1976. fVelocity[2] -= floatsin(-v_angles[0], degrees) * maxSpeed
  1977. entity_set_vector(id, EV_VEC_velocity, fVelocity)
  1978. }
  1979. if((buttonPressed & IN_FORWARD) && (buttonPressed & IN_MOVERIGHT) && !(buttonPressed & IN_MOVELEFT) && !(buttonPressed & IN_BACK)){
  1980. entity_get_vector(id, EV_VEC_v_angle, v_angles)
  1981. v_angles[1] += 135.0
  1982. fVelocity[0] -= floatcos(v_angles[1], degrees) * maxSpeed
  1983. fVelocity[1] -= floatsin(v_angles[1], degrees) * maxSpeed
  1984. fVelocity[2] -= floatsin(-v_angles[0], degrees) * maxSpeed
  1985. entity_set_vector(id, EV_VEC_velocity, fVelocity)
  1986. }
  1987. if((buttonPressed & IN_BACK) && (buttonPressed & IN_MOVELEFT) && !(buttonPressed & IN_MOVERIGHT) && !(buttonPressed & IN_FORWARD)){
  1988. entity_get_vector(id, EV_VEC_v_angle, v_angles)
  1989. v_angles[1] += 135.0
  1990. fVelocity[0] = floatcos(v_angles[1], degrees) * maxSpeed
  1991. fVelocity[1] = floatsin(v_angles[1], degrees) * maxSpeed
  1992. fVelocity[2] = floatsin(-v_angles[0], degrees) * maxSpeed
  1993. entity_set_vector(id, EV_VEC_velocity, fVelocity)
  1994. }
  1995. if((buttonPressed & IN_BACK) && (buttonPressed & IN_MOVERIGHT) && !(buttonPressed & IN_MOVELEFT) && !(buttonPressed & IN_FORWARD)){
  1996. entity_get_vector(id, EV_VEC_v_angle, v_angles)
  1997. v_angles[1] += 45.0
  1998. fVelocity[0] -= floatcos(v_angles[1], degrees) * maxSpeed
  1999. fVelocity[1] -= floatsin(v_angles[1], degrees) * maxSpeed
  2000. fVelocity[2] = floatsin(-v_angles[0], degrees) * maxSpeed
  2001. entity_set_vector(id, EV_VEC_velocity, fVelocity)
  2002. }
  2003. if(!(buttonPressed & IN_BACK) && !(buttonPressed & IN_MOVERIGHT) && !(buttonPressed & IN_MOVELEFT) && !(buttonPressed & IN_FORWARD)){
  2004. fVelocity[0] = 0.0
  2005. fVelocity[1] = 0.0
  2006. fVelocity[2] = 1.0
  2007. entity_set_vector(id, EV_VEC_velocity, fVelocity)
  2008. }
  2009. }
  2010. }
  2011.  
  2012. /*====================================================================================================
  2013. [Create EndZone Entity]
  2014.  
  2015. Purpose: Create an EndZone Entity with a hitbox.
  2016.  
  2017. Comment: To make a hitbox the entity requires a model. So I gave it one and made its
  2018. visibility zero.
  2019.  
  2020. =====================================================================================================*/
  2021. createEndZone() {
  2022. g_EndzoneEntity = create_entity("info_target")
  2023. if (g_EndzoneEntity) {
  2024.  
  2025. entity_set_string(g_EndzoneEntity,EV_SZ_classname,"EndZone")
  2026. entity_set_model(g_EndzoneEntity, ENDZONE_MODEL)
  2027. set_pev(g_EndzoneEntity,pev_solid,SOLID_TRIGGER)
  2028. set_pev(g_EndzoneEntity,pev_movetype,MOVETYPE_NONE)
  2029.  
  2030. new Float:MinBox[3]
  2031. new Float:MaxBox[3]
  2032. MinBox[0] = -25.0
  2033. MinBox[1] = -25.0
  2034. MinBox[2] = -36.0
  2035. MaxBox[0] = 25.0
  2036. MaxBox[1] = 25.0
  2037. MaxBox[2] = 36.0
  2038.  
  2039. entity_set_vector(g_EndzoneEntity, EV_VEC_mins, MinBox)
  2040. entity_set_vector(g_EndzoneEntity, EV_VEC_maxs, MaxBox)
  2041.  
  2042. set_entity_visibility(g_EndzoneEntity, 0)
  2043.  
  2044. //Use this entity's think to show the special effects.
  2045. entity_set_float(g_EndzoneEntity, EV_FL_nextthink, halflife_time() + PULSE_FREQUENCY)
  2046.  
  2047. }
  2048. }
  2049.  
  2050. /*====================================================================================================
  2051. [Special Effects]
  2052.  
  2053. Purpose: Create Special Effect every PULSE_FREQUENCY seconds
  2054.  
  2055. Comment: Message is BROADCAST meaning it sends the message to player without waiting for approval
  2056. that they received it.
  2057.  
  2058. =====================================================================================================*/
  2059. public setEffects(effectID)
  2060. {
  2061. if(g_bIsSurf) {
  2062. new Float:effectOrig[3], iEffectOrig[3]
  2063. entity_get_vector(effectID,EV_VEC_origin,effectOrig)
  2064.  
  2065. for(new x=0;x<3;x++)
  2066. iEffectOrig[x] = floatround(effectOrig[x])
  2067.  
  2068. specialFX(iEffectOrig)
  2069.  
  2070. }
  2071. if(g_EndzoneEntity)
  2072. entity_set_float(effectID, EV_FL_nextthink, halflife_time() + PULSE_FREQUENCY)
  2073. }
  2074.  
  2075. public specialFX(meorig[3]) {
  2076. //lightning beam
  2077. new freq = floatround(PULSE_FREQUENCY * 10.0)
  2078. message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  2079. write_byte(0)
  2080. write_coord(meorig[0]) //(start positionx)
  2081. write_coord(meorig[1]) //(start positiony)
  2082. write_coord(meorig[2] - 20) //(start positionz)
  2083. write_coord(meorig[0]) //(end positionx)
  2084. write_coord(meorig[1]) //(end positiony)
  2085. write_coord(meorig[2] + 75) //(end positionz)
  2086. write_short(g_fxBeamSprite) //(sprite index)
  2087. write_byte(0) //(starting frame)
  2088. write_byte(0) //(frame rate in 0.1's)
  2089. write_byte(freq) //(life in 0.1's)
  2090. write_byte(25) //(line width in 0.1's)
  2091. write_byte(100) //(noise amplitude in 0.01's)
  2092. write_byte(LINE_COLOR_RED) //r
  2093. write_byte(LINE_COLOR_GREEN) //g
  2094. write_byte(LINE_COLOR_BLUE) //b
  2095. write_byte(255) //brightness
  2096. write_byte(1) //(scroll speed in 0.1's)
  2097. message_end()
  2098.  
  2099. //wave
  2100. message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
  2101. write_byte( 21 )
  2102. write_coord(meorig[0])
  2103. write_coord(meorig[1])
  2104. write_coord(meorig[2] - 20)
  2105. write_coord(meorig[0])
  2106. write_coord(meorig[1])
  2107. write_coord(meorig[2] + 100)
  2108. write_short( g_fxWave )
  2109. write_byte( 0 ) // startframe
  2110. write_byte( 0 ) // framerate
  2111. write_byte(freq) // life 2
  2112. write_byte( 15 ) // width 16
  2113. write_byte( 20 ) // noise
  2114. write_byte( WAVE_COLOR_RED ) // r
  2115. write_byte( WAVE_COLOR_GREEN ) // g
  2116. write_byte( WAVE_COLOR_BLUE ) // b
  2117. write_byte( 255 ) //brightness
  2118. write_byte( 5 / 10 ) // speed
  2119. message_end()
  2120. }
Add Comment
Please, Sign In to add comment