#pragma dynamic 131072 //I used to much memory =( /* * ==================================================================================================== * ==================================================================================================== * ---------------------------SURF_OLYMPICS-v1.5.2a--------BY: OneEyed--------------------------- * ==================================================================================================== * ==================================================================================================== * COMMENTS: * Install the plugin normally, and get ready to beat some freagin records! * ==================================================================================================== * REQUIRED: * AMXX 1.70 * * MODULES: * CSTRIKE * ENGINE * FAKEMETA * NVAULT * ==================================================================================================== * CVARS: * surf_flyspeed <#> - Changes flying speed of surf_endzone tool * surf_teamstack < 0 | 1 | 2 > - Forces players to be in a certain team. * surf_godmode < 0 | 1 > - Enables/Disables godmode on players. * surf_semiclip < 0 | 1 > - Enables/Disables semi-clip on players. * * COMMANDS: * surf_endzone - Enables Surf EndZone Creation Tool * surf_delete - Enables Map Record Catagory Deletion menu. * surf_on < 0 | 1 > - Enables/Disables plugin 99%. * * CHAT COMMANDS: * /spec - Makes you a spectator. * /respawn - Respawns you. * /top3 - Opens Map Top Records list. * /help - Opens help menu. * * ==================================================================================================== * PLUGIN DETAILS: * When you spawn in, your in standby mode. As soon as you jump, your game is activated and your * records get recorded. Current records are Map Completion, Speed, Hang Time, Distance, and * Height. The plugin automatically respawns users when you die or fall down. Players also have * a simulated Semi-clip, so they don't get stuck inside each other, but still allow to block * each other. To complete the map, touch the designated EndZone lightning bolt. * * ==================================================================================================== * CREDITS: * - Rukia found how to know if your on ladder. (drove me nuts yet it was so easy) * - teame06/VEN for HLTV event. * - teame06 help with new menu system, and Team_Select menu, and some inspiration =). * - Xtrem3 found a major hang time exploit. * - iron helix found a major height exploit. * - XAD - used the same font color from his statsx motd. * - door for helping me test some features. * - Gorlag/Batman for his Flying code. * - BASIC-MASTER, I copied his Special Effect. (not the code, just effect) * - BAILOPAN for some of the weapon removal code from CSDM v1. * - BAILOPAN, for his information on code optimization. (READ IT) * -- http://www.sourcemod.net/devlog/?p=62 * ==================================================================================================== * CHANGELOG: * * v1.5.2a: * - Reverted back to old method, will crash again on surf_xss and surf_maya * if you have plugins that precache models. It's the maps fault for having * to many brush models. Attempting to fix, completely breaks my plugin on normal maps. * * v1.5.2: * - Fixed crashing in surf_xss and surf_maya. * * v1.5.1: * - Fixed a bug with the semi-clip cvar. * - Fixed a entity leak error with weapon removal. * * v1.5: * - Commentator can be turned on/off through a #define. * - New CVARs: * - surf_godmode < 0 | 1 > (Turns God Mode OFF/ON, for everyone.) * - surf_semiclip < 0 | 1 > (Turns Semi-Clip OFF/ON, for everyone.) * - New Commands: * - surf_delete (Opens menu to delete records of current map.) * - surf_on < 0 | 1 > (Turns plugin OFF/ON completely.) * - Reworked Top Record System: * - One person can't dominate an entire record, there will always be three * - different players for every record catagory. Saved by STEAMID not name. * - Weapons from game_player_equip entity are removed upon death, to prevent spam. * - Players can now easily jump on top of users in Semi-Clip mode. * * v1.1: * - Changed the HUD system a little bit, to be less laggy. * - Fixed an accidental logical error with clearing airtype records. * - Blocked trigger_hurts that heal from teleporting. * - Added Personal Statistics to /top3 window. * ==================================================================================================== */ /*======== User Changeable Defines =========*/ //Uncomment to add commentator text. //#define COMMENTATOR #define STATS_COLOR_RED 255 #define STATS_COLOR_GREEN 180 #define STATS_COLOR_BLUE 0 #define STATS_LOC_X 1.0 #define STATS_LOC_Y 0.5 #define RECORDS_HUD_DELAY 7.0 #define RECORD_COLOR_RED 220 #define RECORD_COLOR_GREEN 80 #define RECORD_COLOR_BLUE 0 #define RECORD_LOC_X 1.0 #define RECORD_LOC_Y 0.30 //EndZone Special Effects #define PULSE_FREQUENCY 0.4 //in seconds #define LINE_COLOR_RED 255 #define LINE_COLOR_GREEN 255 #define LINE_COLOR_BLUE 255 #define WAVE_COLOR_RED 0 #define WAVE_COLOR_GREEN 255 #define WAVE_COLOR_BLUE 0 /*==========================================*/ /*======================ONLY CODERS BEYOND THIS POINT!!=======================================*/ /*======================ONLY CODERS BEYOND THIS POINT!!=======================================*/ /*======================ONLY CODERS BEYOND THIS POINT!!=======================================*/ /*==================================================================================================== How To Add A custom Record: Update the globals to add your custom record info. Scroll down to [Custom Records] and create your custom record function and math there and at the end add the template Validate_BeatRecord. If you have any global vars for your custom record, drop them inside the clean up functions, so they get reset. After that, add your custom record function inside the core named JudgeJudy. ====================================================================================================*/ #include #include #include #include #include #include new Vault static const VAULTNAME[] = "MapRecords" new Vault_EndZone static const ENDZONE_VAULT[] = "EndZones" #define MAX_BUFFER_LENGTH 2047 #define MAX_TEXT_LENGTH 100 #define MAX_PLAYERS 32 /****************************************************/ /**************** Editable Globals ******************/ #define NUMRANKS 3 #define NUMRECORDS 5 //Record Types in order. enum { UKONCZONE = 1, PREDKOSC, CZASLOTU, ODLEGLOSC, WYSOKOSC } //These records require players to be in the air for recording. #define NUM_AIR_RECORDS 3 new AIR_RECORDS[NUM_AIR_RECORDS] = { CZASLOTU, ODLEGLOSC, WYSOKOSC } //These records are read at all times. #define NUM_ANYTIME_RECORDS 1 new ANYTIME_RECORDS[NUM_ANYTIME_RECORDS] = { PREDKOSC } //I predefined up to 7th rank. Be warned, show_motd can only hold 2047 characters in total. //4 ranks uses nearly all that. So some changes will need to be made if u want to display more. //You shouldn't need more than 4, cause the records end up being very close to each other. static const RANKS[NUMRANKS+1][] = { "NULL", "st", "nd", "rd" /* "th", "th", "th", "th" */ } //The Titles order must match enum up top. static const TITLES[NUMRECORDS+1][] = { "NULL", "Ukonczone", "Predkosc", "Czas lotu", "Odleglosc", "Wysokosc" } //symbols records use, order must match enum up top. static const TYPES[NUMRECORDS+1][] = { "NULL", "sec", "mph", "sec", "ft", "ft" } #if defined COMMENTATOR static const BAD_COMMENT[4][] = { "Wipe Out!", "OUCH!", "That's gotta hurt!", "Try Again!" } static const GOOD_COMMENT[5][] = { "Way to go!", "Awesome!", "Nice!", "Spectacular!", "That's OUTRAGEOUS!" } #endif /****************************************************/ /**************** Record Variables ******************/ //Saved Personal Best Record new Float:g_fPersonalRecord[MAX_PLAYERS+1][NUMRECORDS+1] //Current Record of current run (prevents multiple records for top records in one jump) new Float:g_fPersonalOld[MAX_PLAYERS+1][NUMRECORDS+1] //Top Records of map 1st/2nd/3rd new Float:g_fTopRecord[NUMRECORDS+1][NUMRANKS+1] //For quick data accessing new g_TopRecordName[NUMRECORDS+1][NUMRANKS+1][MAX_TEXT_LENGTH+1] new g_TopRecordSteamId[NUMRECORDS+1][NUMRANKS+1][MAX_TEXT_LENGTH+1] /****************************************************/ /************ Custom Record Variables ***************/ new Float:g_fTimeElapsed[MAX_PLAYERS+1] new Float:g_fvecEndOrigin[MAX_PLAYERS+1][3] //Where we currently are. new Float:g_fvecPrevOrigin[MAX_PLAYERS+1][3] //For Teleport Menu (Prev Location). new Float:g_fHeight[MAX_PLAYERS+1] //Height we reached. new g_vecStartOrigin[MAX_PLAYERS+1][3] //Where we took off from wave/jump. new bool:g_bDistCheck[MAX_PLAYERS+1] //When to calculate distance. /****************************************************/ /****************** Event Flags *********************/ new Float:g_Gametime new Float:g_fShowHudDelay[MAX_PLAYERS+1] new Float:g_fIsInAir[MAX_PLAYERS+1] //If this is not equal to current get_gametime(), player is in AIR. new bool:g_bPlaystarted[MAX_PLAYERS+1] new bool:g_bRespawning[MAX_PLAYERS+1] new bool:g_bPlaying[MAX_PLAYERS+1] new bool:g_bIsDead[MAX_PLAYERS+1] //record beating flags, so we don't update only once... appropriately new bool:g_bCheckPersonal[MAX_PLAYERS+1][NUMRECORDS+1] new bool:g_bCheckTop[MAX_PLAYERS+1][NUMRECORDS+1] /****************************************************/ /**************** Hud Text Messages *****************/ new g_StatText[MAX_PLAYERS+1][NUMRECORDS + 1][MAX_TEXT_LENGTH + 1] new g_RecordText[MAX_PLAYERS+1][NUMRECORDS + 1][MAX_TEXT_LENGTH + 1] new HudText_Records[MAX_BUFFER_LENGTH + 1] new HudText_Stats[MAX_BUFFER_LENGTH + 1] /****************************************************/ /****************** Misc Variables ******************/ new bool:g_bIsSurf new bool:g_bRunOnce new g_Maxplayers new g_MapName[64] new g_EndRound new g_NoClip //endzone misc. new bool:g_bModifyMode[MAX_PLAYERS+1] new bool:g_IsFlying[MAX_PLAYERS+1] new bool:g_bFinished[MAX_PLAYERS+1] //menus new menu_teleport new menu_modify[MAX_PLAYERS+1] new menu_finished[MAX_PLAYERS+1] new menu_help new menu_savecheck new menu_deletecheck new menu_deleterecords /****************************************************/ /************** Special FX Variables ****************/ new g_fxBeamSprite, g_fxWave /****************************************************/ /**************** Entity Variables ******************/ //game_player_equip weapons new g_StartWeap[32][64] new g_TotalWeap //teleport destinations new g_TotalTeleDest new g_TeleDest[100][32] new g_TeleDestId[100] //trigger_teleports new g_TotalTeleports new g_TriggerTeleport[100][32] new g_TriggerTeleId[100] //trigger hurts with healing new g_TriggerHurtHealers[100] new g_TrigHurtHealTotal //linked info_target_destination & trigger_teleport new g_LinkedTeleAndDest[100][2] new g_TotalLinked //spawns info new g_InfoPlayerStart new g_InfoPlayerDeathmatch new bool:g_bBothTeamsActive //EndZone Vars new g_EndzoneEntity static const ENDZONE_MODEL[] = "models/chick.mdl" //this will be invisible (needed to set a bounding box) /****************************************************/ //==================================================================================================== static const TITLE[] = "surf_olympics" static const VERSION[] = "1.5.2a" static const AUTHOR[] = "OneEyed" //==================================================================================================== /*==================================================================================================== [Initialize] Purpose: Prepares the map by automating a bunch of information at start of map, so plugin won't lag during gameplay. Also validates if we're on a SURF_MAP. If not plugin disables itself 100%. Comment: Added CVAR for internet query lookup of plugin. ====================================================================================================*/ public plugin_init() { register_plugin(TITLE,VERSION,AUTHOR) register_cvar(TITLE,"0",FCVAR_SERVER) if(g_bIsSurf) set_cvar_num(TITLE,1) else { set_cvar_num(TITLE,0) return PLUGIN_HANDLED } PRECACHE_MODELS() g_Maxplayers = get_maxplayers() //Find if map is missing a teams spawn points. if(g_InfoPlayerDeathmatch == 0 || g_InfoPlayerStart == 0) g_bBothTeamsActive = true LoadMenus() register_cvar("surf_flyspeed","1500") register_cvar("surf_teamstack","0") register_cvar("surf_semiclip","1") register_cvar("surf_godmode","0") register_clcmd("say /spec","cmdSpectate") register_clcmd("say /respawn","cmdRespawn") register_clcmd("say_team /respawn","cmdRespawn") register_clcmd("say /top3","recordLookUp") register_clcmd("say_team /top3","recordLookUp") register_clcmd("say","handle_say") register_clcmd("say_team", "handle_say") register_concmd("surf_on","cmdEnable",ADMIN_RCON,"<0|1> Enable / Disable Surf Olympics") register_concmd("surf_delete","cmdDeleteRecords",ADMIN_RCON, " Deletes Top Map Records by Type.") register_concmd("surf_endzone","cmdEZModify",ADMIN_RCON," Easy Endzone Creator!") register_menucmd(register_menuid("Team_Select",1), (1<<0)|(1<<1)|(1<<4)|(1<<5), "team_select") register_event("DeathMsg", "Event_DeathMsg", "a") register_event("ResetHUD", "Event_ResetHUD", "be") register_event("SendAudio","Event_EndRound","a","2=%!MRAD_terwin","2=%!MRAD_ctwin","2=%!MRAD_rounddraw") register_event("TextMsg","Event_EndRound","a","1=4","2=#Game_Commencing") register_event("HLTV","Event_StartRound","a","1=0","2=0") register_touch("trigger_hurt", "player", "Touch_TriggerHurt") register_touch("trigger_teleport", "player", "Touch_Teleport") //These are our slopes, considered like your in the air to EV_INT_flags so we need them. register_touch("player", "worldspawn", "Touch_World") register_touch("player", "func_water", "Touch_World") register_touch("player", "func_wall", "Touch_World") register_touch("player", "func_breakable", "Touch_World") register_touch("EndZone", "player", "Touch_EndZone") register_touch("player", "player", "Touch_Player") //CORE Loop //Meanest bitch of the south! new judge = create_entity("info_target") if (judge) { entity_set_string(judge, EV_SZ_classname, "JudgeJudy") entity_set_float(judge, EV_FL_nextthink, halflife_time() + 0.1) register_think("JudgeJudy", "JudgeJudy") } register_think("EndZone","setEffects") LoadRecords() return PLUGIN_HANDLED } PRECACHE_MODELS() { if(g_bIsSurf) { engfunc( EngFunc_PrecacheModel, "models/chick.mdl"); g_fxBeamSprite = engfunc( EngFunc_PrecacheModel,"sprites/lgtning.spr")//engfunc( EngFunc_PrecacheModel, g_fxWave = engfunc( EngFunc_PrecacheModel,"sprites/shockwave.spr")//engfunc( EngFunc_PrecacheModel, } } /*==================================================================================================== [Core] Purpose: This is the core, it runs every 0.1 seconds. Scans through all players. Works by knowing when player enters team, dies, jumps to begin session, if player is in the air for record logging, and prints their HUD of information. All record checks are activated here, except for map completion. Comment: The core of the plugin lies in Judge Judy's hands, so RESPECT! If your smart, you can add your own custom records to it. ====================================================================================================*/ public JudgeJudy(judge) { if(!g_EndRound && g_bIsSurf) { g_Gametime = get_gametime() g_NoClip = get_cvar_num("surf_semiclip") for(new id=1;id<=g_Maxplayers;id++) { if(!is_user_connected(id) || g_bModifyMode[id]) continue new team = get_user_team(id) if( team == 1 || team == 2 ) { if(!g_bBothTeamsActive) check_team(id,team) if(!is_user_alive(id)) { if(!g_bIsDead[id]) { g_bIsDead[id] = true set_task(0.5,"AutoRespawn",id) } g_fIsInAir[id] = g_Gametime + 0.1 continue } //part of semi-clip if(entity_get_int(id,EV_INT_solid) != SOLID_BBOX) entity_set_int(id,EV_INT_solid,SOLID_BBOX) new flags = entity_get_int(id, EV_INT_flags) new grounded = on_ground(id,flags) new bool:playstarted2 = g_bPlaystarted[id] // Time Elapsed Timer showTimeElapsed(id,playstarted2) //Player just spawned/teleported in, don't start anything until they touch ground if(!g_bPlaying[id]) { if(grounded) { clearAirRecords(id) g_bPlaying[id] = true } continue } else { entity_get_vector(id,EV_VEC_origin,g_fvecEndOrigin[id]) //player on ground. if(grounded) { Validate_AirChecks(id) clearAirRecords(id) } else if(g_fIsInAir[id] < g_Gametime) //We're in the air do your stuff quickly. { if(!playstarted2) //Player jumped lets begin recording everything { g_fTimeElapsed[id] = g_Gametime playstarted2 = true } if(flags & FL_BASEVELOCITY) //Block Trigger_Push Exploit (but still update HUD) clearAirRecords(id) if(g_bRespawning[id]) { //Fix Teleport/Respawn exploit g_bRespawning[id] = false clearAirRecords(id) } /*Records that require player in air*/ Check_Distance(id) Check_Height(id) Check_HangTime(id) /************************************/ } /*Records of player at all times*/ Check_Speed(id) /*******************************/ } g_bPlaystarted[id] = playstarted2 showStats(id) //Display HUD } else { if(g_NoClip && entity_get_int(id,EV_INT_solid) != SOLID_NOT) entity_set_int(id, EV_INT_solid, SOLID_NOT) } } } entity_set_float(judge, EV_FL_nextthink, halflife_time() + 0.1) } /*==================================================================================================== [Display HUD] Purpose: Displays Records/Stats to users. show Records is displayed when user respawns/uses command. showStats displays when user is playing. Comment: $$ ====================================================================================================*/ public showRecords(id) { if((g_Gametime - g_fShowHudDelay[id]) > (RECORDS_HUD_DELAY + 1.0)) { new rLen = format(HudText_Records, MAX_BUFFER_LENGTH, "Twoje rekordowe statystyki") for( new x = 2 ; x <= NUMRECORDS ; x++ ) rLen += format(HudText_Records[rLen], MAX_BUFFER_LENGTH-rLen, "%s", g_RecordText[id][x]) rLen += format(HudText_Records[rLen], MAX_BUFFER_LENGTH-rLen, "%s", g_RecordText[id][UKONCZONE]) 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) show_hudmessage(id,"%s",HudText_Records) g_fShowHudDelay[id] = g_Gametime } } public showTimeElapsed(id, bool:started) { if(g_EndzoneEntity && !g_bFinished[id] && started) { format(g_StatText[id][UKONCZONE],MAX_TEXT_LENGTH,"^nTwoj obecny czas %.1f sek",(g_Gametime - g_fTimeElapsed[id])) 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) show_hudmessage(id,"%s",g_StatText[id][UKONCZONE]) } else g_StatText[id][UKONCZONE][0] = 0 } public showStats(id) { HudText_Stats[0] = 0 new sLen = 0 for( new x = 2 ; x <= NUMRECORDS ; x++ ) sLen += format(HudText_Stats[sLen], MAX_BUFFER_LENGTH-sLen, "%s", g_StatText[id][x]) 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) show_hudmessage(id,"%s",HudText_Stats) } /*==================================================================================================== [Custom Records] Purpose: Our record keepings are done here. Comment: Use the template Validate_BeatRecord for custom records if you want records to be beaten more than once in an entire run. Unlike check completion, which is checked once when player reaches endzone. ====================================================================================================*/ Check_HangTime(id) { //check for a serious ladder exploit new startEnt, cn[64] while((startEnt = find_ent_in_sphere(startEnt,g_fvecEndOrigin[id],45.0)) != 0) { if(is_user_connected(startEnt) || !is_valid_ent(startEnt)) continue entity_get_string(startEnt,EV_SZ_classname,cn,63) if(equal(cn,"func_ladder")) { g_fIsInAir[id] = g_Gametime return PLUGIN_HANDLED } } new Float:pHangtime = (g_Gametime - g_fIsInAir[id]) Validate_BeatRecord(id, CZASLOTU, pHangtime) return PLUGIN_HANDLED } Check_Speed(id) { new Float:pSpeed = float(get_speed(id)) / 18.0 Validate_BeatRecord(id, PREDKOSC, pSpeed) } Check_Distance(id) { if(g_bDistCheck[id]) { g_vecStartOrigin[id][0] = floatround(g_fvecEndOrigin[id][0]) g_vecStartOrigin[id][1] = floatround(g_fvecEndOrigin[id][1]) g_bDistCheck[id] = false } else { new newdist[3] newdist[0] = floatround(g_fvecEndOrigin[id][0]) newdist[1] = floatround(g_fvecEndOrigin[id][1]) new Float:pDist = float(get_distance(g_vecStartOrigin[id],newdist)) / 16.5 Validate_BeatRecord(id, ODLEGLOSC, pDist) } } Check_Height(id) { new Float:jHeight = (g_fvecEndOrigin[id][2] - g_fHeight[id]) / 8.0 if(jHeight < 0.0) return Validate_BeatRecord(id, WYSOKOSC, jHeight) return } Float:Check_Completion(id) { //use get_gametime() to get a more accurate reading. new Float:fCompletion = get_gametime() - g_fTimeElapsed[id] format(g_StatText[id][UKONCZONE],MAX_TEXT_LENGTH,"^nTwoj czas to: %.2f sekund",fCompletion) if(fCompletion < g_fPersonalRecord[id][UKONCZONE]) { g_fPersonalRecord[id][UKONCZONE] = fCompletion format(g_RecordText[id][UKONCZONE],MAX_TEXT_LENGTH,"^nUkonczone w %.2f sekund",fCompletion) } g_fPersonalOld[id][UKONCZONE] = fCompletion Check_TopRecord(id, UKONCZONE, 1) return fCompletion } /*==================================================================================================== [Validation] Purpose: If we beat a personal record, automatically update it. If we beat a Top 3 record, do a check to find what rank our player reached. Cascade our top_records down a rank respectively. Comment: If you add a custom record, use the Validate BeatRecord template. ====================================================================================================*/ Validate_BeatRecord(id, recordtype, Float:jRecord) { //Format HUD Stat String of recordtype format(g_StatText[id][recordtype], MAX_TEXT_LENGTH, "^n%s -- %.2f %s", TITLES[recordtype], jRecord, TYPES[recordtype]) //If our running statistic beats players record of current session, update it //and check if it beat a personal/top record, if so, mark its flag. if(jRecord > g_fPersonalOld[id][recordtype]) { g_fPersonalOld[id][recordtype] = jRecord //save their best (for current session) if(jRecord > g_fPersonalRecord[id][recordtype]) // beat their own record g_bCheckPersonal[id][recordtype] = true if(jRecord > g_fTopRecord[recordtype][NUMRANKS]) //beat lowest rank g_bCheckTop[id][recordtype] = true } } //Validate our checks Validate_AirChecks(id) { for( new x = 0 ; x < NUM_AIR_RECORDS ; x++ ) { if(g_bCheckPersonal[id][AIR_RECORDS[x]]) Set_PersonalRecord(id, AIR_RECORDS[x]) if(g_bCheckTop[id][AIR_RECORDS[x]]) Check_TopRecord(id, AIR_RECORDS[x], 0) } } Validate_OtherChecks(id) { for( new x = 0 ; x < NUM_ANYTIME_RECORDS ; x++ ) { if(g_bCheckPersonal[id][ANYTIME_RECORDS[x]]) Set_PersonalRecord(id, ANYTIME_RECORDS[x]) if(g_bCheckTop[id][ANYTIME_RECORDS[x]]) Check_TopRecord(id, ANYTIME_RECORDS[x], 0) } } //Update their Personal Record Set_PersonalRecord(id, recordtype) { new Float:jRecord = g_fPersonalOld[id][recordtype] format(g_RecordText[id][recordtype], MAX_TEXT_LENGTH, "^n%s -- %.2f %s", TITLES[recordtype], jRecord, TYPES[recordtype]) g_fPersonalRecord[id][recordtype] = jRecord g_bCheckPersonal[id][recordtype] = false } Check_TopRecord(id, recordtype, iftype) { new hasrank, authid[32], x get_user_authid(id,authid,31) //Do we have a record in the list? for( x = 1 ; x <= NUMRANKS ; x++ ) if(equali(g_TopRecordSteamId[recordtype][x][0],authid)) { hasrank = x break } new endrank = ( (hasrank > 0) ? hasrank : NUMRANKS ) new Float:jRecord = g_fPersonalOld[id][recordtype] //Difference is the greaterthan / lesserthan signs switch(iftype) { case 0: { for( x = 1 ; x <= endrank ; x++ ) if(jRecord > g_fTopRecord[recordtype][x]) { Set_TopRecord(id, authid, recordtype, x, jRecord, hasrank) break } } case 1: { for( x = 1 ; x <= endrank ; x++ ) if(jRecord < g_fTopRecord[recordtype][x]) { Set_TopRecord(id, authid, recordtype, x, jRecord, hasrank) break } } } g_bCheckTop[id][recordtype] = false } //We don't allow double records, only update users record. Set_TopRecord(id, authid[], recordtype, rank, Float:jRecord, hasrank) { new name[MAX_TEXT_LENGTH+1] get_user_name(id,name,MAX_TEXT_LENGTH) replace(name,MAX_TEXT_LENGTH,"<","(") //These symbols screw up html, replace(name,MAX_TEXT_LENGTH,">",")") //if user has them in their name. replace(name,MAX_TEXT_LENGTH,"&","&") new temp, x if(hasrank) //Update according to their current saved rank. { for( x = hasrank; x >= rank ; x-- ) if(x == rank) saveRecord(authid, name, rank, recordtype, jRecord) else { temp = x-1 //temp rank (helps amxx run faster) saveRecord(g_TopRecordSteamId[recordtype][temp], g_TopRecordName[recordtype][temp], x, recordtype, g_fTopRecord[recordtype][temp]) } } else //No saved rank, cascade ranks down from current { for( x = NUMRANKS; x >= rank ; x-- ) if(x == rank) saveRecord(authid, name, x, recordtype, jRecord) else { temp = x-1 //temp rank (helps amxx run faster) saveRecord(g_TopRecordSteamId[recordtype][temp], g_TopRecordName[recordtype][temp], x, recordtype, g_fTopRecord[recordtype][temp]) } } } /*==================================================================================================== [Touched] Purpose: These functions are for certain events for when player touches what we specified. Mostly record checks. Comment: $$ ====================================================================================================*/ public Touch_Teleport(teleport, id) { if(!g_EndRound && g_bIsSurf) { g_bRespawning[id] = true //If player touches teleport, check their records immediately if they have one Validate_AirChecks(id) //same as above Validate_OtherChecks(id) #if defined COMMENTATOR new rand = random_num(0,3) client_print(id, print_chat, "%s", GOOD_COMMENT[rand]) #endif } } //stop players stucking inside each other, still allow semi block public Touch_Player(id, otherPlayer) { if(!g_bModifyMode[id] && !g_bModifyMode[otherPlayer] && g_bIsSurf) { clearAirRecords(id) //Exploit Fix. if(g_NoClip) { if(entity_get_int(id, EV_INT_solid) != SOLID_NOT) entity_set_int(id, EV_INT_solid, SOLID_NOT) if(entity_get_int(otherPlayer, EV_INT_solid) != SOLID_NOT) entity_set_int(otherPlayer, EV_INT_solid, SOLID_NOT) //Allow players to jump/stack on each other new buttonPressed = entity_get_int(id, EV_INT_button) if( (buttonPressed & IN_JUMP) ) { new Float:jVel[3] entity_get_vector(id,EV_VEC_velocity,jVel) jVel[2] = 375.0 entity_set_vector(id,EV_VEC_velocity,jVel) } } } } //touched func_wall/worldspawn/func_water public Touch_World(id, world) { if(!g_EndRound && g_bIsSurf) { if(!g_bRespawning[id]) Validate_AirChecks(id) clearAirRecords(id) } return PLUGIN_HANDLED } //respawn player, compensate for if olympics is turned off public Touch_TriggerHurt(hurt, id) { if(is_user_alive(id)) { new bool:check for(new x=0;x
") add(msg,2046,"

Pomoc w surfowaniu


") add(msg,2046,"Zeby surfowac podazaj za stokiem. Nigdy nie uzywaj w ani s!!
") add(msg,2046,"Zeby sie obracac, uzywaj a i d(strafe)
") add(msg,2046,"Surfowanie po wodzie:spacja+ctrl (+jump oraz +duck)
") add(msg,2046,"Plugin przetlumaczony przez naven'a www.Cs-Wies.eu") add(msg,2046,"

") show_motd(id,msg,help_title) } case 2: { client_print(id,print_chat,"[Surf] - zeby wyswietlic top3 serwera, wpisz /top3") } case 3: { client_print(id,print_chat,"[Surf] - Wpisz /respawn zeby wrocic na respa, lub odzyskac zycie.") } case 4: { new help_title[64], msg[2047] format(help_title,63,"Zasady Surf Olympics") add(msg,2046,"
") add(msg,2046,"

Zasady Surf Olympics


") add(msg,2046,"1. Zeby pobic rekord wysokosci lub odleglosci, nie mozesz sie respawnowac podczas skoku,
") add(msg,2046,"2. Mozesz pobic rekord predkosci kiedy sie teleportujesz lub respawnujesz,
") add(msg,2046,"3. Zeby ukonczyc mape, musisz dotknac swiecacego okregu,
") add(msg,2046,"4. Twoje personalne rekordy zostaja usuniete, kiedy opuscisz serwer,
") add(msg,2046,"5. Jesli pobijesz jakis rekord, twoj nick zostanie wyswietlony w top3, wpisz /top3 zeby je zobaczyc.") add(msg,2046,"

") show_motd(id,msg,help_title) } case 5: { client_print(id,print_chat,"[Surf_Olympics] - surf_olympics v%s By: %s",VERSION,AUTHOR) client_print(id,print_chat,"[Surf_Olympics] - Plugin dostepny na http://www.amxmodx.org/forums/viewtopic.php?p=223786 oraz Cs-Wies.eu") } } menu_display(id, menu_help, 0) } return PLUGIN_HANDLED } /*==================================================================================================== [Team Control] Purpose: Force Players into specified team by CVAR surf_teamstack Comment: $$ ====================================================================================================*/ public team_select(id, key) { if(!g_bBothTeamsActive && g_bIsSurf) { new teamstack = get_cvar_num("surf_teamstack") if(teamstack == 1 || teamstack == 2) { if(key != 5 && key != teamstack-1) { new message[64] switch(teamstack) { case 1: format(message, 63, "Musisz wybrac druzyne Terrorystow!") case 2: format(message, 63, "Musisz wybrac druzyne Counter-Terrorist") } message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("StatusText"), {0, 0, 0}, id); write_byte(0); write_string(message); message_end(); engclient_cmd(id,"chooseteam") return PLUGIN_HANDLED } } } return PLUGIN_CONTINUE } check_team(id,team) { new teamstack = get_cvar_num("surf_teamstack") //if user not in correct team, fix them if(teamstack == 1 || teamstack == 2) { if(team != teamstack) { new randModel switch(teamstack) { case 1: randModel = random_num(1,4) case 2: randModel = random_num(1,5) } select_model(id,teamstack,randModel) } } } public cmdSpectate(id) select_model(id,3, 0) //random model selecting for teamstack select_model(id,team, model) { switch(team) { case 1: { switch(model) { case 1: cs_set_user_team(id, CS_TEAM_T, CS_T_TERROR) case 2: cs_set_user_team(id, CS_TEAM_T, CS_T_LEET) case 3: cs_set_user_team(id, CS_TEAM_T, CS_T_ARCTIC) case 4: cs_set_user_team(id, CS_TEAM_T, CS_T_GUERILLA) } } case 2: { switch(model) { case 1: cs_set_user_team(id, CS_TEAM_CT, CS_CT_URBAN) case 2: cs_set_user_team(id, CS_TEAM_CT, CS_CT_GSG9) case 3: cs_set_user_team(id, CS_TEAM_CT, CS_CT_SAS) case 4: cs_set_user_team(id, CS_TEAM_CT, CS_CT_GIGN) case 5: cs_set_user_team(id, CS_TEAM_CT, CS_CT_VIP) //my lil secret } } case 3: { cs_set_user_team(id, CS_TEAM_SPECTATOR, CS_DONTCHANGE) if(is_user_alive(id)) user_kill(id) } } } public client_command(id) { if(g_bIsSurf && get_cvar_num("surf_teamstack") > 0) { new arg[64] read_argv( 0, arg , 63 ) if( equal("chooseteam",arg) || equal("jointeam",arg) ) { return PLUGIN_HANDLED } } return PLUGIN_CONTINUE } /*==================================================================================================== [Remove Weapons] Purpose: Remove the weapon listed in game_player_equip entity, (since this will be the most dropped). Comment: Thanks to BAILOPAN on this safe weapon removal method. ====================================================================================================*/ public Event_DeathMsg() { if(g_bIsSurf) { new player = read_data(2) if(player) { new wps[32], num, i, Drop[1] get_user_weapons(player, wps, num) //catch every dropped weapon! for (i=0; i 0) { wfEnt = find_ent_by_class(wEnt, name) woEnt = entity_get_edict(wEnt, EV_ENT_owner) if (woEnt > 32 && woEnt == weapbox) remove_entity(wEnt) wEnt = wfEnt } } /*==================================================================================================== [nVault Data Handling] Purpose: Saves/Loads EndZone Location origin to file. Also save record, saves to vault and cascades records down a rank. LoadRecord is called once at map load, to load records saved in vault. RecordLookup is called when player types /top3 and formats it to fit on MOTD window. Comment: $$ ====================================================================================================*/ SaveEndZoneLocation(Float:ezOrig[3]) { Vault_EndZone = nvault_open( ENDZONE_VAULT ) if(Vault_EndZone == INVALID_HANDLE) server_print("Error opening nVault file: %s",ENDZONE_VAULT) new key[64], update[511] format(key,63,"%s",g_MapName) format(update,510,"^"%f^" ^"%f^" ^"%f^"",ezOrig[0],ezOrig[1],ezOrig[2]) if(ezOrig[0] != 0.0 && ezOrig[1] != 0.0 && ezOrig[2] != 0.0) { if(!g_EndzoneEntity) createEndZone() entity_set_origin(g_EndzoneEntity,ezOrig) } nvault_set(Vault_EndZone, key, update) //update End Zone Location nvault_close(Vault_EndZone) for( new x = 1 ; x <= NUMRANKS ; x++ ) saveRecord("0", "Nobody", x, UKONCZONE, 9999.9) for( new x = 1 ; x <= g_Maxplayers ; x++ ) g_fPersonalRecord[x][UKONCZONE] = 9999.0 } LoadEndZoneLocation() { Vault_EndZone = nvault_open( ENDZONE_VAULT ) if(Vault_EndZone == INVALID_HANDLE) server_print("Error opening nVault file: %s",ENDZONE_VAULT) new key[64], val[511], TimeStamp new endzoneOrig[3][64] format(key,63,"%s",g_MapName) //Retrieve origin from file, parse it, convert to float, and set it to endzone model. if( nvault_lookup(Vault_EndZone, key, val, 510, TimeStamp) ) { parse(val, endzoneOrig[0], 63, endzoneOrig[1], 63, endzoneOrig[2], 63) new Float:ezOrig[3] for(new x=0;x<3;x++) ezOrig[x] = floatstr(endzoneOrig[x]) if(ezOrig[0] != 0 && ezOrig[1] != 0 && ezOrig[2] != 0) createEndZone() if(g_EndzoneEntity) entity_set_origin(g_EndzoneEntity,ezOrig) nvault_close(Vault_EndZone) } else nvault_close(Vault_EndZone) } saveRecord(authid[], name[], rank, recordtype, Float:record) { Vault = nvault_open( VAULTNAME ) if(Vault == INVALID_HANDLE) server_print("Blad przy otwieraniu pliku: nVault : %s",VAULTNAME) new key[64], update[511] format(key,63,"%s %i %i",g_MapName,rank,recordtype) format(update,510,"^"%s^" ^"%s^" ^"%f^"", authid, name, record) format(g_TopRecordSteamId[recordtype][rank],MAX_TEXT_LENGTH,"%s",authid) //steamid format(g_TopRecordName[recordtype][rank],MAX_TEXT_LENGTH,"%s",name) //name g_fTopRecord[recordtype][rank] = record nvault_set(Vault, key, update) nvault_close(Vault) } LoadRecords() { Vault = nvault_open( VAULTNAME ) if(Vault == INVALID_HANDLE) server_print("Blad przy otwieraniu pliku: nVault : %s",VAULTNAME) new key[64], value[511], TimeStamp new playerinfo[3][MAX_TEXT_LENGTH+1] // "STEAMID" "NICK" "RECORD" new empty[511], full[511] //full is for completion to == 9999.0 format(full,510,"^"0^" ^"Nobody^" ^"9999.0^"") format(empty,510,"^"0^" ^"Nobody^" ^"0.0^"") for( new x = 1 ; x <= NUMRECORDS ; x++ ) { for( new m = 1 ; m <= NUMRANKS ; m++ ) { format(key,63,"%s %i %i",g_MapName,m,x) if( nvault_lookup(Vault, key, value, 510, TimeStamp) ) { parse(value, playerinfo[0], MAX_TEXT_LENGTH, playerinfo[1], MAX_TEXT_LENGTH, playerinfo[2], MAX_TEXT_LENGTH) g_fTopRecord[x][m] = floatstr(playerinfo[2]) format(g_TopRecordSteamId[x][m],MAX_TEXT_LENGTH,"%s",playerinfo[0]) //steamid format(g_TopRecordName[x][m],MAX_TEXT_LENGTH,"%s",playerinfo[1]) //name } else { //Fill empty slots if(x == UKONCZONE) nvault_set(Vault, key, full) //Fill in None and 9999.0 else nvault_set(Vault, key, empty) //Fill in None and 0.0 format(g_TopRecordSteamId[x][m],MAX_TEXT_LENGTH,"0") //steamid format(g_TopRecordName[x][m],MAX_TEXT_LENGTH,"Nobody") //name } } } nvault_close(Vault) } public recordLookUp(id) { Vault = nvault_open( VAULTNAME ) if(Vault == INVALID_HANDLE) server_print("Blad przy otwieraniu pliku: nVault %s",VAULTNAME) new key[64], value[511], TimeStamp new rankings[MAX_BUFFER_LENGTH+1], map[64] new Float:record new playerinfo[3][MAX_TEXT_LENGTH+1] // "STEAMID" "NICK" "RECORD" new rLen = 0 format(map,63,"Najlepsze rekordy: %s ",g_MapName) rLen += format(rankings,MAX_BUFFER_LENGTH,"
") //Write personal record statistics rLen += format(rankings[rLen],MAX_BUFFER_LENGTH-rLen,"

Personalne statystyki
") for( new x = 1 ; x <= NUMRECORDS ; x++ ) { if( x == UKONCZONE && !g_EndzoneEntity ) continue //No EndZone, skip completions! rLen += format(rankings[rLen],MAX_BUFFER_LENGTH-rLen,"%s: %.2f %s
",TITLES[x],g_fPersonalRecord[id][x],TYPES[x]) } rLen += format(rankings[rLen],MAX_BUFFER_LENGTH-rLen,"

") //Write top record statistics for( new x = 1 ; x <= NUMRECORDS ; x++ ) { if( x == UKONCZONE && !g_EndzoneEntity ) continue //No EndZone, skip completions! rLen += format(rankings[rLen],MAX_BUFFER_LENGTH-rLen,"

Rekord %s
",TITLES[x]) for( new m = 1 ; m <= NUMRANKS ; m++ ) { format(key,63,"%s %i %i",g_MapName,m,x) if( nvault_lookup(Vault, key, value, 510, TimeStamp) ) { parse(value, playerinfo[0], MAX_TEXT_LENGTH, playerinfo[1], MAX_TEXT_LENGTH, playerinfo[2], MAX_TEXT_LENGTH) record = floatstr(playerinfo[2]) rLen += format(rankings[rLen],MAX_BUFFER_LENGTH-rLen,"%i%s : %s %.2f %s
",m,RANKS[m],playerinfo[1],record,TYPES[x]) } } rLen += format(rankings[rLen],MAX_BUFFER_LENGTH-rLen,"

") } nvault_close(Vault) show_motd(id,rankings,map) } /*==================================================================================================== [Keyvalue] Purpose: Since this runs before plugin_precache and plugin_init, find out if it's a surf map here. Then disable all damage from trigger_hurts and func_water, disable kill buttons. Also save target/targetname and id's of trigger_teleport, info_teleport_destination, and info_target. Comment: This function runs whenever something spawns, but for these entities, it is used only at map load. ==================================================================================================*/ public pfn_keyvalue(entid) { if(!g_bRunOnce) { get_mapname(g_MapName,64) if(containi(g_MapName, "surf") != -1 || containi(g_MapName, "wurf") != -1) g_bIsSurf = true else g_bIsSurf = false g_bRunOnce = true } if(g_bIsSurf) { new classname[32], key[32], value[32] copy_keyvalue(classname, 31, key, 31, value, 31) if(equal(classname,"env_explosion")) remove_entity(entid) /***** Remove damage from entities *****/ if(equal(classname,"func_water")) if(equal(key,"lip")) DispatchKeyValue("lip","0") if(equal(key, "dmg")) if(floatstr(value) > 0.0) //Only cancel damage, some trigger_hurts give HP DispatchKeyValue("dmg","0") if(equal(key, "damagetype")) DispatchKeyValue("damagetype","0") /***************************************/ /*********** trigger_hurt healers **********/ if(equali(classname,"trigger_hurt")) if(equali(key,"dmg")) if(floatstr(value) < 0.0) g_TriggerHurtHealers[g_TrigHurtHealTotal++] = entid /*******************************************/ /******* Player Equip Weapon Info ******/ if( (equali(classname,"game_player_equip")) && (containi(key,"weapon_") != -1) && (!equali(key,"weapon_knife")) ) format(g_StartWeap[g_TotalWeap++],63,"%s",key) /***************************************/ /************* Player Spawn Info *******/ if(equal(classname, "info_player_start")) g_InfoPlayerStart++ if(equal(classname, "info_player_deathmatch")) g_InfoPlayerDeathmatch++ /***************************************/ /*********** Teleport Info *************/ if(equal(classname, "info_teleport_destination") || equal(classname, "info_target") || equal(classname, "trigger_teleport")) if(equal(key, "targetname")) { //save "targetname" to link to target and save ID format(g_TeleDest[g_TotalTeleDest],31,"%s",value) g_TeleDestId[g_TotalTeleDest++] = entid } if(equal(classname, "trigger_teleport")) { if(equal(key, "target")) { //save "target" to link to targetname and save ID format(g_TriggerTeleport[g_TotalTeleports],31,"%s",value) g_TriggerTeleId[g_TotalTeleports++] = entid } } /***************************************/ } } /*==================================================================================================== [EndZone Tool & Other Menus Setup] Purpose: Link our target/targetnames into one array and save id's of linked trigger_teleport/destinations. After that, create our EndZone entity, with a bounding box. Search if map has a saved origin for it and apply, if not don't create entity. Finally create several of our menus automatically based on information we have. Comment: This is done on mapload, and never again. =====================================================================================================*/ LoadMenus() { new targetName[100][32] //Save the target name for tele menu //Link teleport <-> destination for(new x=0;x Comment: $$ ====================================================================================================*/ public cmdEnable(id,level,cid) { if (!cmd_access(id,level,cid,1)) return PLUGIN_HANDLED new arg[32], status read_argv(1,arg,31) status = str_to_num(arg) if(status == 1) { set_cvar_num(TITLE,1) g_bIsSurf = true client_print(0,print_chat,"[Surf Olympics] Plugin jest wlaczony.") new team for(new id=1;id<=g_Maxplayers;id++) { team = get_user_team(id) if(is_user_connected(id) && (team == 1 || team == 2)) AutoRespawn(id) } } else { set_cvar_num(TITLE,0) g_bIsSurf = false client_print(0,print_chat,"[Surf Olympics] Plugin jest wylaczony.") } return PLUGIN_HANDLED } /*==================================================================================================== [Delete Record Menu] Purpose: Opens a menu for deleting ALL records or by Record Type. COMMAND: surf_delete Comment: $$ ====================================================================================================*/ public cmdDeleteRecords(id, level, cid) { if( g_bIsSurf && (id > 0) && (id <= g_Maxplayers) && is_user_connected(id) && cmd_access(id,level,cid,0)) menu_display(id, menu_deleterecords, 0) return PLUGIN_HANDLED } public DeleteRecord_Handler(id, menu, item) { if(is_user_connected(id)) { if(item == MENU_EXIT || !g_bIsSurf) { return PLUGIN_HANDLED } new cmd[6], iName[64]; new access, callback; menu_item_getinfo(menu, item, access, cmd,5, iName, 63, callback); new recordtype = str_to_num(cmd) new delRecord[MAX_TEXT_LENGTH+1] if(recordtype != 0) format(delRecord,MAX_TEXT_LENGTH,"(Usuwanie %s rekordow) Jestes pewien?",TITLES[recordtype]) else format(delRecord,MAX_TEXT_LENGTH,"(Usuwanie WSZYSTKICH rekordow) Jestes pewien") new menu_areyousure = menu_create(delRecord, "DelCheck_Handler") menu_additem(menu_areyousure, "YES", cmd, ADMIN_RCON) menu_additem(menu_areyousure, "CANCEL", "500", ADMIN_RCON) menu_setprop(menu_areyousure, MPROP_EXIT, MEXIT_NEVER); menu_display(id, menu_areyousure, 0) } return PLUGIN_HANDLED } public DelCheck_Handler(id, menu, item) { if(is_user_connected(id)) { new cmd[6], iName[64]; new access, callback; menu_item_getinfo(menu, item, access, cmd,5, iName, 63, callback); new recordtype = str_to_num(cmd) new Float:record if(recordtype == 0) //All Records { for( new m = 1 ; m <= NUMRECORDS ; m++ ) { if(m == UKONCZONE) record = 9999.9 else record = 0.0 for(new x=1;x<=NUMRANKS;x++) saveRecord("0", "Nikt", x, m, record) } } else if(recordtype != 500) //Single Record Type { if(recordtype == UKONCZONE) record = 9999.9 for( new x = 1 ; x <= NUMRANKS ; x++ ) saveRecord("0", "Nikt", x, recordtype, record) } } } /*==================================================================================================== [EndZone Creation Tool] Purpose: surf_endzone admin command. This handles all the EndZone Tool features. COMMAND: surf_endzone Comment: I tried making it flexible for the average user. Even allows some cool combos. ====================================================================================================*/ public cmdEZModify(id,level,cid) { if(!g_bIsSurf) { client_print(id,print_chat,"[Surf Olympics] ERROR: Surf Olympics musi byc aktywowany aby to wlaczyc.") return PLUGIN_HANDLED } if(!id) { server_print("[Surf Olympics] ERROR: surf_endzone jest komenda uzywana TYLKO podczas gry!.") return PLUGIN_HANDLED } new CsTeams:team = cs_get_user_team(id)//get_user_team(id) if (!cmd_access(id,level,cid,0) || g_EndRound || !is_user_alive(id) || (team != CS_TEAM_T && team != CS_TEAM_CT)) return PLUGIN_HANDLED g_bModifyMode[id] = true entity_set_float(id,EV_FL_takedamage,0.0) if(!g_EndzoneEntity) { menu_item_setname(menu_modify[id],5, "(NULL) Skasuj EndZone") menu_item_setname(menu_modify[id],0, "Stworz tutaj EndZone") } else { menu_item_setname(menu_modify[id],5, "Skasuj EndZone") menu_item_setname(menu_modify[id],0, "Przenies EndZone tutaj") } menu_item_setname(menu_modify[id],1, "NoClip(OFF)") menu_item_setname(menu_modify[id], 2, "Latanie (OFF)") menu_display(id, menu_modify[id], 0) return PLUGIN_HANDLED } public Endzone_Handler(id, menu, item) { if(is_user_connected(id)) { if(item == MENU_EXIT || !g_bIsSurf) { g_IsFlying[id] = false g_bModifyMode[id] = false AutoRespawn(id) return PLUGIN_HANDLED } switch(item) { case 0: //save loc to file { menu_display(id, menu_savecheck, 0) return PLUGIN_HANDLED } case 1: //noclip on/off (cancel out flying) { new movetype = entity_get_int(id, EV_INT_movetype) switch(movetype) { case MOVETYPE_NOCLIP: { entity_set_int(id, EV_INT_movetype, MOVETYPE_WALK) menu_item_setname(menu, item, "NoClip (OFF)") } case MOVETYPE_WALK: { entity_set_int(id, EV_INT_movetype, MOVETYPE_NOCLIP) menu_item_setname(menu, item, "NoClip (ON)") menu_item_setname(menu, item+1, "Latanie (OFF)") g_IsFlying[id] = false } } } case 2: //flying on/off (cancel out noclip) { if(!g_IsFlying[id]) { g_IsFlying[id] = true menu_item_setname(menu, item-1, "NoClip (OFF)") menu_item_setname(menu, item, "Latanie (ON)") entity_set_int(id, EV_INT_movetype, MOVETYPE_WALK) } else { g_IsFlying[id] = false menu_item_setname(menu, item, "Latanie (OFF)") } } case 3: //teleport menu { menu_display(id, menu_teleport, 0) return PLUGIN_HANDLED } case 4: //go to endzone location { if(!g_EndzoneEntity) client_print(id,print_chat,"[Surf Olympics] - Nie ma jeszcze zadnego EndZone!") else { new Float:ezEntOrig[3] entity_get_vector(g_EndzoneEntity,EV_VEC_origin,ezEntOrig) entity_set_origin(id,ezEntOrig) new Float:temp_vel[3] entity_set_vector(id,EV_VEC_velocity,temp_vel) } } case 5: { if(!g_EndzoneEntity) client_print(id,print_chat,"[Surf Olympics] - Nie ma juz EndZone do usuniecia!") else { menu_display(id, menu_deletecheck, 0) return PLUGIN_HANDLED } } } if(item != MENU_EXIT && item != MENU_BACK && item != MENU_MORE) menu_display(id, menu_modify[id], 0) } return PLUGIN_HANDLED } public Delete_Handler(id, menu, item) { if(is_user_connected(id)) { if(item == 0 ) { remove_entity(g_EndzoneEntity) g_EndzoneEntity = 0 new Float:nullOrig[3] SaveEndZoneLocation(nullOrig) menu_item_setname(menu_modify[id],5, "(NULL) Skasuj EndZone") menu_item_setname(menu_modify[id],0, "Stworz EndZone tutaj") } menu_display(id,menu_modify[id], 0) } return PLUGIN_HANDLED } public Save_Handler(id, menu, item) { if(is_user_connected(id)) { if(item == 0) { new Float:myorig[3] entity_get_vector(id,EV_VEC_origin,myorig) menu_item_setname(menu_modify[id],5, "Skasuj EndZone") menu_item_setname(menu_modify[id],0, "Stworz EndZone tutaj") SaveEndZoneLocation(myorig) } menu_display(id,menu_modify[id], 0) } return PLUGIN_HANDLED } public Teleport_Handler(id, menu, item) { if(is_user_connected(id)) { if(item == MENU_EXIT) { menu_display(id, menu_modify[id], 0) return PLUGIN_HANDLED } new cmd[6], iName[64]; new access, callback; menu_item_getinfo(menu, item, access, cmd,5, iName, 63, callback); //If user teleports by accident, this allows them to return to their location. if(item > -1) { if(str_to_num(cmd) == 1) { if(g_fvecPrevOrigin[id][0] == 0.0 && g_fvecPrevOrigin[id][1] == 0.0 && g_fvecPrevOrigin[id][2] == 0.0) { menu_display(id, menu_modify[id], 0) return PLUGIN_HANDLED } //setting origin doesn't remove users velocity, so do it for them. new Float:temp_vel[3] entity_set_vector(id,EV_VEC_velocity,temp_vel) entity_set_origin(id,g_fvecPrevOrigin[id]) menu_display(id, menu_modify[id], 0) return PLUGIN_HANDLED } new teleport_id = str_to_num(cmd) entity_get_vector(id,EV_VEC_origin,g_fvecPrevOrigin[id]) //Save location to go back (Previous Location) fake_touch(teleport_id,id) //fake touch chosen teleport menu_display(id, menu_modify[id], 0) } } return PLUGIN_HANDLED } /*==================================================================================================== [Fly Mode] Purpose: The ability to fly allows the ADMIN to create EndZone locations much faster and easier. Comment: This was created by Gorlag/Batman. FULL CREDIT to him for this Flying mode. =====================================================================================================*/ public client_PreThink(id) { if( g_bIsSurf && g_IsFlying[id] ) define_flyMovements(id) } public define_flyMovements(id) { new maxSpeed = get_cvar_num("surf_flyspeed") new Float:fVelocity[3], Float:v_angles[3] new flag = entity_get_int(id, EV_INT_flags) new buttonPressed = entity_get_int(id, EV_INT_button) if(flag & FL_ONGROUND){ if(buttonPressed & IN_JUMP){ entity_ge