diff --git a/gameserver/addons/sourcemod/scripting/cpMod/commands.sp b/gameserver/addons/sourcemod/scripting/cpMod/commands.sp index 2da096b..744576f 100644 --- a/gameserver/addons/sourcemod/scripting/cpMod/commands.sp +++ b/gameserver/addons/sourcemod/scripting/cpMod/commands.sp @@ -86,6 +86,18 @@ public SaveClientLocation(client) //if plugin is enabled if(g_bEnabled) { + if(Timer_IsPlayerTouchingStartZone(client)) + { + PrintToChat(client, "Not allowed inside start zones,"); + return; + } + + if(Timer_IsPlayerTouchingZoneType(client, ZtAntiCp)) + { + PrintToChat(client, "You are insiade an Ati CP zone."); + return; + } + //if player on ground if(GetEntDataEnt2(client, FindSendPropOffs("CBasePlayer", "m_hGroundEntity")) != -1 || g_bAir) { @@ -94,9 +106,16 @@ public SaveClientLocation(client) //if player has less than limit checkpoints if(whole < CPLIMIT) { + if(!g_bRestore) + { + if(!Timer_GetPauseStatus(client)) + Timer_Pause(client); + } + else Timer_Reset(client); + //save some data GetClientAbsOrigin(client, g_fPlayerCords[client][whole]); - GetClientAbsAngles(client, g_fPlayerAngles[client][whole]); + GetClientEyeAngles(client, g_fPlayerAngles[client][whole]); GetEntPropVector(client, Prop_Data, "m_vecVelocity", g_fPlayerVelocity[client][whole]); g_iPlayerLevel[client][whole] = Timer_GetClientLevel(client); @@ -115,7 +134,15 @@ public SaveClientLocation(client) } } else if(whole == CPLIMIT) - { //cp rotation enabled + { + if(!g_bRestore) + { + if(!Timer_GetPauseStatus(client)) + Timer_Pause(client); + } + else Timer_Reset(client); + + //cp rotation enabled new current = g_CurrentCp[client]; //if last slot reached @@ -204,6 +231,8 @@ public TeleClient(client,pos) else Client_TelePos(client, pos); } +new g_iSelectedPos[MAXPLAYERS+1]; + public Client_TelePos(client, pos) { //if no valid player @@ -213,60 +242,81 @@ public Client_TelePos(client, pos) //if plugin is enabled if(g_bEnabled) { - if(g_timer) Timer_Reset(client); - - new current = g_CurrentCp[client]; - new whole = g_WholeCp[client]; - - //if on last slot and next - if(current == whole-1 && pos == 1) + if(g_timer) { - //reset to first - g_CurrentCp[client] = -1; - current = -1; + if(!g_bRestore) + { + if(!Timer_GetPauseStatus(client)) + Timer_Pause(client); + } + else Timer_Reset(client); } - //if on first slot and previous - if(current == 0 && pos == -1) + + g_iSelectedPos[client] = pos; + CreateTimer(0.0, Timer_TelePos, client); //Bugfix + } + else //plugin disabled + PrintToChat(client, "%t", "PluginDisabled", YELLOW,LIGHTGREEN,YELLOW); +} + +public Action:Timer_TelePos(Handle:timer, any:client) +{ + if(!IsClientInGame(client)) + return Plugin_Stop; + + new current = g_CurrentCp[client]; + new whole = g_WholeCp[client]; + + //if on last slot and next + if(current == whole-1 && g_iSelectedPos[client] == 1) + { + //reset to first + g_CurrentCp[client] = -1; + current = -1; + } + //if on first slot and previous + if(current == 0 && g_iSelectedPos[client] == -1) + { + //reset to last + g_CurrentCp[client] = whole; + current = whole; + } + + new actual = current+g_iSelectedPos[client]; + + //if not valid checkpoint + //if(actual < 0 || actual > whole || (g_fPlayerCords[client][actual][0] == 0.0 && g_fPlayerCords[client][actual][1] == 0.0 && g_fPlayerCords[client][actual][2] == 0.0)){ + if(actual < 0 || actual > whole) + { + PrintToChat(client, "%t", "CpNotFound", YELLOW,LIGHTGREEN,YELLOW); + } + else + { + if(g_timerMapzones) { - //reset to last - g_CurrentCp[client] = whole; - current = whole; + if(Timer_IsPlayerTouchingStartZone(client)) + Timer_SetIgnoreEndTouchStart(client, 1); } - new actual = current+pos; + Timer_RestoreLastJumps(client); - //if not valid checkpoint - //if(actual < 0 || actual > whole || (g_fPlayerCords[client][actual][0] == 0.0 && g_fPlayerCords[client][actual][1] == 0.0 && g_fPlayerCords[client][actual][2] == 0.0)){ - if(actual < 0 || actual > whole) + if(g_bVelocity) + TeleportEntity(client, g_fPlayerCords[client][actual], g_fPlayerAngles[client][actual], g_fPlayerVelocity[client][actual]); + else TeleportEntity(client, g_fPlayerCords[client][actual], g_fPlayerAngles[client][actual], Float:{0.0,0.0,-100.0});//stop him + PrintToChat(client, "%t", "CpTeleported", YELLOW,LIGHTGREEN,YELLOW,GREEN,actual+1,whole,YELLOW); + g_CurrentCp[client] += g_iSelectedPos[client]; + + if(g_bEffects) { - PrintToChat(client, "%t", "CpNotFound", YELLOW,LIGHTGREEN,YELLOW); - } - else - { - if(g_timerMapzones) - { - if(Timer_IsPlayerTouchingZoneType(client, ZtStart) || Timer_IsPlayerTouchingZoneType(client, ZtBonusStart)) - Timer_SetIgnoreEndTouchStart(client, 1); - } - - if(g_bVelocity) - TeleportEntity(client, g_fPlayerCords[client][actual], g_fPlayerAngles[client][actual], g_fPlayerVelocity[client][actual]); - else TeleportEntity(client, g_fPlayerCords[client][actual], g_fPlayerAngles[client][actual], Float:{0.0,0.0,-100.0});//stop him - PrintToChat(client, "%t", "CpTeleported", YELLOW,LIGHTGREEN,YELLOW,GREEN,actual+1,whole,YELLOW); - g_CurrentCp[client] += pos; - - if(g_bEffects) - { - EmitSoundToClient(client,"buttons/blip1.wav",client); - TE_SetupBeamRingPoint(g_fPlayerCords[client][actual],10.0,200.0,g_BeamSpriteRing2,0,0,10,1.0,50.0,0.0,{255,255,255,255},0,0); - TE_SendToClient(client); - } - - Timer_SetClientLevel(client, g_iPlayerLevel[client][actual]); + EmitSoundToClient(client,"buttons/blip1.wav",client); + TE_SetupBeamRingPoint(g_fPlayerCords[client][actual],10.0,200.0,g_BeamSpriteRing2,0,0,10,1.0,50.0,0.0,{255,255,255,255},0,0); + TE_SendToClient(client); } + + Timer_SetClientLevel(client, g_iPlayerLevel[client][actual]); } - else //plugin disabled - PrintToChat(client, "%t", "PluginDisabled", YELLOW,LIGHTGREEN,YELLOW); + + return Plugin_Stop; } ConfirmAbortMenu(client, pos) diff --git a/gameserver/addons/sourcemod/scripting/cpMod/sql.sp b/gameserver/addons/sourcemod/scripting/cpMod/sql.sp index 641e7b8..438f25b 100644 --- a/gameserver/addons/sourcemod/scripting/cpMod/sql.sp +++ b/gameserver/addons/sourcemod/scripting/cpMod/sql.sp @@ -140,7 +140,11 @@ public db_insertPlayer(client){ decl String:szSteamId[32]; decl String:szUName[MAX_NAME_LENGTH]; //get some playerinformation - GetClientAuthString(client, szSteamId, 32); + #if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7 + GetClientAuthId(client, AuthId_Steam2, szSteamId, sizeof(szSteamId)); + #else + GetClientAuthString(client, szSteamId, sizeof(szSteamId)); + #endif GetClientName(client, szUName, MAX_NAME_LENGTH); decl String:szName[MAX_NAME_LENGTH*2+1]; @@ -161,7 +165,11 @@ public db_updatePlayerCheckpoint(client, current){ decl String:szSteamId[32]; //get some playerinformation GetClientName(client, szUName, MAX_NAME_LENGTH); - GetClientAuthString(client, szSteamId, 32); + #if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7 + GetClientAuthId(client, AuthId_Steam2, szSteamId, sizeof(szSteamId)); + #else + GetClientAuthString(client, szSteamId, sizeof(szSteamId)); + #endif decl String:szName[MAX_NAME_LENGTH*2+1]; //escape some quote characters that could mess up the szQuery @@ -200,7 +208,11 @@ public SQL_SelectPlayerCallback(Handle:owner, Handle:hndl, const String:error[], public db_selectPlayerCheckpoint(client){ decl String:szQuery[255]; decl String:szSteamId[32]; - GetClientAuthString(client, szSteamId, 32); + #if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7 + GetClientAuthId(client, AuthId_Steam2, szSteamId, sizeof(szSteamId)); + #else + GetClientAuthString(client, szSteamId, sizeof(szSteamId)); + #endif Format(szQuery, 255, sql_selectCheckpoint, szSteamId, g_szMapName); diff --git a/gameserver/addons/sourcemod/scripting/disabled/timer-button_announcer.sp b/gameserver/addons/sourcemod/scripting/disabled/timer-button_announcer.sp new file mode 100644 index 0000000..69a7f14 --- /dev/null +++ b/gameserver/addons/sourcemod/scripting/disabled/timer-button_announcer.sp @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include + +public OnPluginStart() +{ + HookEntityOutput( "func_button", "OnPressed", pressed); + HookEntityOutput( "func_button", "OnDamaged", damaged); +} + +public OnMapStart() +{ + HookEntityOutput( "func_button", "OnPressed", pressed); + HookEntityOutput( "func_button", "OnDamaged", damaged); +} + +public OnMapEnd() +{ + UnhookEntityOutput( "func_button", "OnPressed", pressed); + UnhookEntityOutput( "func_button", "OnDamaged", damaged); +} + + +public damaged(const String:output[], caller, attacker, Float:Any) +{ + if(Client_IsValid(attacker, true)) CPrintToChat(attacker, "%s {yellow}You have shot a button.", PLUGIN_PREFIX2); +} + +public pressed(const String:output[], caller, attacker, Float:Any) +{ + if(Client_IsValid(attacker, true) && Client_HasButtons(attacker, IN_USE)) CPrintToChat(attacker, "%s {yellow}You have pressed a button.", PLUGIN_PREFIX2); +} \ No newline at end of file diff --git a/gameserver/addons/sourcemod/scripting/disabled/timer-mapchooser_sounds.sp b/gameserver/addons/sourcemod/scripting/disabled/timer-mapchooser_sounds.sp new file mode 100644 index 0000000..f0f9e9f --- /dev/null +++ b/gameserver/addons/sourcemod/scripting/disabled/timer-mapchooser_sounds.sp @@ -0,0 +1,599 @@ +/** + * Sound support for Mapchooser Extended + * Inspired by QuakeSounds 2.7 + */ + +#pragma semicolon 1 +#include +#include +#include + +#define VERSION "1.10.1" + +#define CONFIG_FILE "configs/mapchooser_extended/sounds.cfg" +#define CONFIG_DIRECTORY "configs/mapchooser_extended/sounds" + +#define SET_NAME_MAX_LENGTH 64 + +// 0-60, even though we don't ever call 0 +// Counter-intuitive note: This array has 61 elements, not 60 +#define COUNTER_MAX_SIZE 60 +// The number of digits in the previous number +#define COUNTER_MAX_SIZE_DIGITS 2 + +#define NUM_TYPES 5 + +// CVar Handles +new Handle:g_Cvar_EnableSounds = INVALID_HANDLE; +new Handle:g_Cvar_EnableCounterSounds = INVALID_HANDLE; +new Handle:g_Cvar_SoundSet = INVALID_HANDLE; +new Handle:g_Cvar_DownloadAllSounds = INVALID_HANDLE; + +// Data Handles +new Handle:g_TypeNames = INVALID_HANDLE; // Maps SoundEvent enumeration values to KeyValue section names +new Handle:g_SetNames = INVALID_HANDLE; +new Handle:g_SoundFiles = INVALID_HANDLE; +new Handle:g_CurrentSoundSet = INVALID_HANDLE; // Lazy "pointer" to the current sound set. Updated on cvar change or map change. + +//Global variables +new bool:g_DownloadAllSounds; + +new bool:g_bNeedsFakePrecache = false; + +enum SoundEvent +{ + SoundEvent_Counter = 0, + SoundEvent_VoteStart = 1, + SoundEvent_VoteEnd = 2, + SoundEvent_VoteWarning = 3, + SoundEvent_RunoffWarning = 4, +} + +enum SoundType +{ + SoundType_None, + SoundType_Sound, + SoundType_Builtin, + SoundType_Event +} + +enum SoundStore +{ + String:SoundStore_Value[PLATFORM_MAX_PATH], + SoundType:SoundStore_Type +} + +public Plugin:myinfo = +{ + name = "Mapchooser Extended Sounds", + author = "Powerlord", + description = "Sound support for Mapchooser Extended", + version = VERSION, + url = "https://forums.alliedmods.net/showthread.php?t=156974" +} + +// Map enum values to their named values +// This is used for searching later. +PopulateTypeNamesArray() +{ + if (g_TypeNames == INVALID_HANDLE) + { + g_TypeNames = CreateArray(ByteCountToCells(SET_NAME_MAX_LENGTH), NUM_TYPES); + SetArrayString(g_TypeNames, _:SoundEvent_Counter, "counter"); + SetArrayString(g_TypeNames, _:SoundEvent_VoteStart, "vote start"); + SetArrayString(g_TypeNames, _:SoundEvent_VoteEnd, "vote end"); + SetArrayString(g_TypeNames, _:SoundEvent_VoteWarning, "vote warning"); + SetArrayString(g_TypeNames, _:SoundEvent_RunoffWarning, "runoff warning"); + } +} + +public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) +{ + MarkNativeAsOptional("GetEngineVersion"); +} + +public OnPluginStart() +{ + g_Cvar_EnableSounds = CreateConVar("mce_sounds_enablesounds", "1", "Enable this plugin. Sounds will still be downloaded (if applicable) even if the plugin is disabled this way.", FCVAR_NONE, true, 0.0, true, 1.0); + g_Cvar_EnableCounterSounds = CreateConVar("mce_sounds_enablewarningcountersounds", "1", "Enable sounds to be played during warning counter. If this is disabled, map vote warning, start, and stop sounds still play.", FCVAR_NONE, true, 0.0, true, 1.0); + g_Cvar_SoundSet = CreateConVar("mce_sounds_soundset", "tf", "Sound set to use, optimized for TF by default. Sound sets are defined in addons/sourcemod/configs/mapchooser_extended_sounds.cfg. Takes effect immediately if sm_mapvote_downloadallsounds is 1, otherwise at map change.", FCVAR_NONE); + g_Cvar_DownloadAllSounds = CreateConVar("mce_sounds_downloadallsounds", "0", "Force players to download all sound sets, so sets can be dynamically changed during the map. Defaults to off. Takes effect at map change.", FCVAR_NONE, true, 0.0, true, 1.0); + CreateConVar("mce_sounds_version", VERSION, "Mapchooser Extended Sounds Version", FCVAR_DONTRECORD|FCVAR_SPONLY|FCVAR_REPLICATED); + + AutoExecConfig(true, "mapchooser_extended_sounds"); + + RegAdminCmd("mce_sounds_reload", Command_Reload, ADMFLAG_CONVARS, "Reload Mapchooser Sound configuration file."); + RegAdminCmd("sm_mapvote_reload_sounds", Command_Reload, ADMFLAG_CONVARS, "Deprecated: use mce_sounds_reload"); + + RegAdminCmd("mce_sounds_list_soundsets", Command_List_Soundsets, ADMFLAG_CONVARS, "List available Mapchooser Extended sound sets."); + RegAdminCmd("sm_mapvote_list_soundsets", Command_List_Soundsets, ADMFLAG_CONVARS, "Deprecated: use mce_sounds_list_soundsets"); + + PopulateTypeNamesArray(); + // LoadSounds needs to be executed even if the plugin is "disabled" via the sm_mapvote_enablesounds cvar. + + g_SetNames = CreateArray(ByteCountToCells(PLATFORM_MAX_PATH)); + g_SoundFiles = CreateTrie(); + LoadSounds(); + HookConVarChange(g_Cvar_SoundSet, SoundSetChanged); + + if (GetEngineVersion() == Engine_CSGO) + { + g_bNeedsFakePrecache = true; + } +} + +// Not sure this is required, but there were some weird crashes when this plugin was unloaded. This is an attempt to fix that. +/* +public OnPluginEnd() +{ + CloseSoundArrayHandles(); +} +*/ + +/* +* Moved to OnConfigsExecuted due to cvar requirements +public OnMapStart() +{ + BuildDownloadsTableAll(); +} +*/ + +public OnConfigsExecuted() +{ + g_DownloadAllSounds = GetConVarBool(g_Cvar_DownloadAllSounds); + + decl String:soundSet[SET_NAME_MAX_LENGTH]; + + // Store which sound set is in use + GetConVarString(g_Cvar_SoundSet, soundSet, sizeof(soundSet)); + + // Unknown sound set from config file, reset to default + if (FindStringInArray(g_SetNames, soundSet) == -1 && !StrEqual(soundSet, "tf", true)) + { + ResetConVar(g_Cvar_SoundSet); + GetConVarString(g_Cvar_SoundSet, soundSet, sizeof(soundSet)); + } + + SetCurrentSoundSet(soundSet); + if (g_DownloadAllSounds) + { + BuildDownloadsTableAll(); + } + else + { + BuildDownloadsTable(g_CurrentSoundSet); + } +} + +public SoundSetChanged(Handle:cvar, String:oldValue[], String:newValue[]) +{ + if (FindStringInArray(g_SetNames, newValue) == -1) + { + LogError("New sound set not found: %s", newValue); + SetConVarString(cvar, oldValue); + } + else if (g_DownloadAllSounds) + { + SetCurrentSoundSet(newValue); + } +} + +public OnMapVoteStarted() +{ + PlaySound(SoundEvent_VoteStart); +} + +public OnMapVoteEnd(const String:map[]) +{ + PlaySound(SoundEvent_VoteEnd); +} + +public OnMapVoteWarningStart() +{ + PlaySound(SoundEvent_VoteWarning); +} + +public OnMapVoteRunnoffWarningStart() +{ + PlaySound(SoundEvent_RunoffWarning); +} + +public OnMapVoteWarningTick(time) +{ + if (GetConVarBool(g_Cvar_EnableSounds) && GetConVarBool(g_Cvar_EnableCounterSounds)) { + decl String:currentType[SET_NAME_MAX_LENGTH]; + decl Handle:counterTrie; + + if (g_CurrentSoundSet != INVALID_HANDLE) + { + if (GetArrayString(g_TypeNames, _:SoundEvent_Counter, currentType, sizeof(currentType)) > 0 && GetTrieValue(g_CurrentSoundSet, currentType, counterTrie)) + { + new String:key[5]; + IntToString(time, key, sizeof(key)); + + new soundData[SoundStore]; + if (!GetTrieArray(counterTrie, key, soundData[0], sizeof(soundData))) + { + return; + } + + if (soundData[SoundStore_Type] == SoundType_Event) + { + new Handle:broadcastEvent = CreateEvent("teamplay_broadcast_audio"); + if (broadcastEvent == INVALID_HANDLE) + { + #if defined DEBUG + LogError("Could not create teamplay_broadcast_event. This may be because there are no players connected."); + #endif + return; + } + SetEventInt(broadcastEvent, "team", -1); + SetEventString(broadcastEvent, "sound", soundData[SoundStore_Value]); + FireEvent(broadcastEvent); + } + else + { + EmitSoundToAll(soundData[SoundStore_Value]); + } + } + } + } +} + +public Action:Command_Reload(client, args) +{ + LoadSounds(); + ReplyToCommand(client, "[MCES] Reloaded sound configuration."); + return Plugin_Handled; +} + +public Action:Command_List_Soundsets(client, args) +{ + new setCount = GetArraySize(g_SetNames); + ReplyToCommand(client, "[SM] The following %d sound sets are installed:", setCount); + for (new i = 0; i < setCount; i++) + { + decl String:setName[SET_NAME_MAX_LENGTH]; + GetArrayString(g_SetNames, i, setName, sizeof(setName)); + ReplyToCommand(client, "[SM] %s", setName); + } +} + +PlaySound(SoundEvent:event) +{ + if (GetConVarBool(g_Cvar_EnableSounds)) + { + if (g_CurrentSoundSet != INVALID_HANDLE) + { + decl String:currentType[SET_NAME_MAX_LENGTH]; + + if (GetArrayString(g_TypeNames, _:event, currentType, sizeof(currentType)) > 0) + { + new soundData[SoundStore]; + GetTrieArray(g_CurrentSoundSet, currentType, soundData[0], sizeof(soundData)); + if (soundData[SoundStore_Type] == SoundType_Event) + { + new Handle:broadcastEvent = CreateEvent("teamplay_broadcast_audio"); + if (broadcastEvent == INVALID_HANDLE) + { + #if defined DEBUG + LogError("Could not create teamplay_broadcast_event. This may be because there are no players connected."); + #endif + return; + } + SetEventInt(broadcastEvent, "team", -1); + SetEventString(broadcastEvent, "sound", soundData[SoundStore_Value]); + FireEvent(broadcastEvent); + } + else + { + EmitSoundToAll(soundData[SoundStore_Value]); + } + } + } + } + +} + +SetCurrentSoundSet(String:soundSet[]) +{ + // Save a reference to the Trie for the current sound set, for use in the forwards below. + // Also do error checking to make sure the set exists. + if (!GetTrieValue(g_SoundFiles, soundSet, g_CurrentSoundSet)) + { + SetFailState("Could not load sound set"); + } + +} + +// Load the list of sounds sounds from the configuration file +// This should be done on plugin load. +// This looks really complicated, but it really isn't. +LoadSounds() +{ + CloseSoundArrayHandles(); + + decl String:directoryPath[PLATFORM_MAX_PATH]; + decl String:modName[SET_NAME_MAX_LENGTH]; + + GetGameFolderName(modName, sizeof(modName)); + + BuildPath(Path_SM, directoryPath, sizeof(directoryPath), CONFIG_DIRECTORY); + + new Handle:directory = OpenDirectory(directoryPath); + if (directory != INVALID_HANDLE) + { + decl String:dirEntry[PLATFORM_MAX_PATH]; + while (ReadDirEntry(directory, dirEntry, sizeof(dirEntry))) + { + new Handle:soundsKV = CreateKeyValues("MapchooserSoundsList"); + decl String:filePath[PLATFORM_MAX_PATH]; + + Format(filePath, sizeof(filePath), "%s/%s", directoryPath, dirEntry); + + if (!DirExists(filePath)) + { + FileToKeyValues(soundsKV, filePath); + + if (KvGotoFirstSubKey(soundsKV)) + { + // Iterate through the sets + do + { + new Handle:setTrie = CreateTrie(); + decl String:currentSet[SET_NAME_MAX_LENGTH]; + new bool:builtinSet = false; + + KvGetSectionName(soundsKV, currentSet, sizeof(currentSet)); + + if (FindStringInArray(g_SetNames, currentSet) == -1) + { + // Add to the list of sound sets + PushArrayString(g_SetNames, currentSet); + } + else + { + SetFailState("Duplicate sound set: %s", currentSet); + } + + if (StrEqual(currentSet, modName, false)) + { + builtinSet = true; + } + + if (KvGotoFirstSubKey(soundsKV)) { + // Iterate through each sound in the set + do + { + decl String:currentType[SET_NAME_MAX_LENGTH]; + KvGetSectionName(soundsKV, currentType, sizeof(currentType)); + // Type to enum mapping + new typeKey = FindStringInArray(g_TypeNames, currentType); + + switch(typeKey) + { + case SoundEvent_Counter: + { + // Counter is special, as it has multiple values + new Handle:counterTrie = CreateTrie(); + + if (KvGotoFirstSubKey(soundsKV)) + { + do + { + // Get the current key + decl String:time[COUNTER_MAX_SIZE_DIGITS + 1]; + + KvGetSectionName(soundsKV, time, sizeof(time)); + + new soundData[SoundStore]; + + // new key = StringToInt(time); + + soundData[SoundStore_Type] = RetrieveSound(soundsKV, builtinSet, soundData[SoundStore_Value], PLATFORM_MAX_PATH); + if (soundData[SoundStore_Type] == SoundType_None) + { + continue; + } + + // This seems wrong, but this is documented on the forums here: https://forums.alliedmods.net/showthread.php?t=151942 + SetTrieArray(counterTrie, time, soundData[0], sizeof(soundData)); + + //SetArrayString(counterArray, key, soundFile); + } while (KvGotoNextKey(soundsKV)); + KvGoBack(soundsKV); + } + + SetTrieValue(setTrie, currentType, _:counterTrie); + + } + + // Set the sounds directly for other types + default: + { + new soundData[SoundStore]; + + soundData[SoundStore_Type] = RetrieveSound(soundsKV, builtinSet, soundData[SoundStore_Value], PLATFORM_MAX_PATH); + + if (soundData[SoundStore_Type] == SoundType_None) + { + continue; + } + + SetTrieArray(setTrie, currentType, soundData[0], sizeof(soundData)); + } + } + } while (KvGotoNextKey(soundsKV)); + KvGoBack(soundsKV); + } + SetTrieValue(g_SoundFiles, currentSet, setTrie); + } while (KvGotoNextKey(soundsKV)); + } + } + CloseHandle(soundsKV); + } + CloseHandle(directory); + } + + if (GetArraySize(g_SetNames) == 0) + { + SetFailState("Could not locate any sound sets."); + } +} + +// Internal LoadSounds function to get sound and type +SoundType:RetrieveSound(Handle:soundsKV, bool:builtin, String:soundFile[], soundFileSize) +{ + if (builtin) + { + // event is considered before builtin, as it has related game data and should always be used in preference to builtin + KvGetString(soundsKV, "event", soundFile,soundFileSize); + + if (!StrEqual(soundFile, "")) + { + return SoundType_Event; + } + + KvGetString(soundsKV, "builtin", soundFile, soundFileSize); + if (!StrEqual(soundFile, "")) + { + return SoundType_Builtin; + } + } + + KvGetString(soundsKV, "sound", soundFile, soundFileSize); + + if (!StrEqual(soundFile, "")) + { + return SoundType_Sound; + } + + // Whoops, didn't find this sound + return SoundType_None; +} + +// Preload all sounds in a set +BuildDownloadsTable(Handle:currentSoundSet) +{ + if (currentSoundSet != INVALID_HANDLE) + { + for (new i = 0; i < GetArraySize(g_TypeNames); i++) + { + decl String:currentType[SET_NAME_MAX_LENGTH]; + GetArrayString(g_TypeNames, i, currentType, sizeof(currentType)); + + switch(i) + { + case SoundEvent_Counter: + { + decl Handle:counterTrie; + if (GetTrieValue(currentSoundSet, currentType, counterTrie)) + { + // Skip value 0 + for (new j = 1; j <= COUNTER_MAX_SIZE; ++j) + { + new String:key[5]; + IntToString(j, key, sizeof(key)); + + new soundData[SoundStore]; + GetTrieArray(counterTrie, key, soundData[0], sizeof(soundData)); + if (soundData[SoundStore_Type] != SoundType_Event) + { + CacheSound(soundData); + } + } + } + } + + default: + { + new soundData[SoundStore]; + GetTrieArray(currentSoundSet, currentType, soundData[0], sizeof(soundData)); + + if (soundData[SoundStore_Type] != SoundType_Event) + { + CacheSound(soundData); + } + } + } + } + } +} + +// Load each set and build its download table +stock BuildDownloadsTableAll() +{ + for (new i = 0; i < GetArraySize(g_SetNames); i++) + { + decl String:currentSet[SET_NAME_MAX_LENGTH]; + decl Handle:currentSoundSet; + GetArrayString(g_SetNames, i, currentSet, sizeof(currentSet)); + + if (GetTrieValue(g_SoundFiles, currentSet, currentSoundSet)) + { + BuildDownloadsTable(currentSoundSet); + } + } +} + +// Found myself repeating this code, so I pulled it into a separate function +CacheSound(soundData[SoundStore]) +{ + if (soundData[SoundStore_Type] == SoundType_Builtin) + { + PrecacheSoundAny(soundData[SoundStore_Value]); + } + else if (soundData[SoundStore_Type] == SoundType_Sound) + { + if (PrecacheSoundAny(soundData[SoundStore_Value])) + { + decl String:downloadLocation[PLATFORM_MAX_PATH]; + Format(downloadLocation, sizeof(downloadLocation), "sound/%s", soundData[SoundStore_Value]); + AddFileToDownloadsTable(downloadLocation); + } else { + LogMessage("Failed to load sound: %s", soundData[SoundStore_Value]); + } + } +} + +// Close all the handles that are children and grandchildren of the g_SoundFiles trie. +stock CloseSoundArrayHandles() +{ + // Close all open handles in the sound set + for (new i = 0; i < GetArraySize(g_SetNames); i++) + { + decl String:currentSet[SET_NAME_MAX_LENGTH]; + decl Handle:trieHandle; + decl Handle:arrayHandle; + + GetArrayString(g_SetNames, i, currentSet, sizeof(currentSet)); + GetTrieValue(g_SoundFiles, currentSet, trieHandle); + // "counter" is an adt_trie, close that too + GetTrieValue(trieHandle, "counter", arrayHandle); + CloseHandle(arrayHandle); + CloseHandle(trieHandle); + } + ClearTrie(g_SoundFiles); + ClearArray(g_SetNames); +} + +stock bool:PrecacheSoundAny( const String:szPath[] ) +{ + if (g_bNeedsFakePrecache) + { + return FakePrecacheSoundEx(szPath); + } + else + { + return PrecacheSound(szPath); + } +} + +stock bool:FakePrecacheSoundEx( const String:szPath[] ) +{ + decl String:szPathStar[PLATFORM_MAX_PATH]; + Format(szPathStar, sizeof(szPathStar), "*%s", szPath); + + AddToStringTable( FindStringTable( "soundprecache" ), szPathStar ); + return true; +} diff --git a/gameserver/addons/sourcemod/scripting/disabled/timer-maplist-helper_css.sp b/gameserver/addons/sourcemod/scripting/disabled/timer-maplist-helper_css.sp new file mode 100644 index 0000000..d63b867 --- /dev/null +++ b/gameserver/addons/sourcemod/scripting/disabled/timer-maplist-helper_css.sp @@ -0,0 +1,208 @@ +#include +#include +#include + +new Handle:g_hSQL = INVALID_HANDLE; +new g_iSQLReconnectCounter; +new String:sql_selectMaps[] = "SELECT map FROM mapzone WHERE type = 0 GROUP BY map ORDER BY map;"; + +public Plugin:myinfo = +{ + name = "[Timer] Maplist Helper", + author = "Zipcore", + description = "Re-writes maplist.txt and mapcycle.txt with valid maps", + version = PL_VERSION, + url = "forums.alliedmods.net/showthread.php?p=2074699" +} + +public OnPluginStart() +{ + if(GetEngineVersion() != Engine_CSS) + { + Timer_LogError("Don't use this plugin for other games than CS:S."); + SetFailState("Check timer error logs."); + return; + } + + RegAdminCmd("sm_maplist_rewrite", Cmd_Rewrite, ADMFLAG_BAN); + RegAdminCmd("sm_nav_create", Cmd_NavCreate, ADMFLAG_BAN); + + if (g_hSQL == INVALID_HANDLE) + { + ConnectSQL(); + } +} + +public OnMapStart() +{ + if (g_hSQL == INVALID_HANDLE) + { + ConnectSQL(); + } +} + +public Action:Cmd_Rewrite(client, args) +{ + ReWriteMaplist(client); + return Plugin_Handled; +} + +public Action:Cmd_NavCreate(client, args) +{ + CreateNavFiles(client); + return Plugin_Handled; +} + +ConnectSQL() +{ + if (g_hSQL != INVALID_HANDLE) + { + CloseHandle(g_hSQL); + } + + g_hSQL = INVALID_HANDLE; + + if (SQL_CheckConfig("timer")) + { + SQL_TConnect(ConnectSQLCallback, "timer"); + } + else + { + SetFailState("PLUGIN STOPPED - Reason: no config entry found for 'timer' in databases.cfg - PLUGIN STOPPED"); + } +} + +public ConnectSQLCallback(Handle:owner, Handle:hndl, const String:error[], any:data) +{ + if (g_iSQLReconnectCounter >= 5) + { + PrintToServer("PLUGIN STOPPED - Reason: reconnect counter reached max - PLUGIN STOPPED"); + return; + } + + if (hndl == INVALID_HANDLE) + { + PrintToServer("Connection to SQL database has failed, Reason: %s", error); + g_iSQLReconnectCounter++; + ConnectSQL(); + return; + } + g_hSQL = CloneHandle(hndl); + + g_iSQLReconnectCounter = 1; +} + +public ReWriteMaplist(client) +{ + decl String:Query[255]; + Format(Query, 255, sql_selectMaps); + SQL_TQuery(g_hSQL, SQL_ReWriteMaplistCallback, Query, client); +} + +public SQL_ReWriteMaplistCallback(Handle:owner, Handle:hndl, const String:error[], any:client) +{ + if (hndl == INVALID_HANDLE) + { + return; + } + + new iMapCount = 0; + + if(SQL_GetRowCount(hndl)) + { + decl String:path[PLATFORM_MAX_PATH]; + decl String:path2[PLATFORM_MAX_PATH]; + Format(path, sizeof(path), "maplist.txt"); + Format(path2, sizeof(path2), "mapcycle.txt"); + new Handle:hfile = OpenFile(path, "w"); + new Handle:hfile2 = OpenFile(path2, "w"); + + decl String:sMap[128]; + + while(SQL_FetchRow(hndl)) + { + SQL_FetchString(hndl, 0, sMap, sizeof(sMap)); + WriteFileLine(hfile, sMap); + WriteFileLine(hfile2, sMap); + iMapCount++; + } + + CloseHandle(hfile); + CloseHandle(hfile2); + } + + PrintToChat(client, "New maplist.txt contains %d maps.", iMapCount); +} + +public CreateNavFiles(client) +{ + decl String:Query[255]; + Format(Query, 255, sql_selectMaps); + SQL_TQuery(g_hSQL, SQL_CreateNavFilesCallback, Query, client); +} + +public SQL_CreateNavFilesCallback(Handle:owner, Handle:hndl, const String:error[], any:client) +{ + if (hndl == INVALID_HANDLE) + { + return; + } + + new iNavCount = 0; + + if(SQL_GetRowCount(hndl)) + { + decl String:sMap[128]; + decl String:sNav[64]; + + while(SQL_FetchRow(hndl)) + { + SQL_FetchString(hndl, 0, sMap, sizeof(sMap)); + + Format(sNav, 64, "maps/%s.nav", sMap); + if(!FileExists(sNav)) + { + File_Copy("maps/base.nav", sNav); + } + } + } + + PrintToChat(client, "Copied %d mssing Nav files", iNavCount); +} + +/* + * Copies file source to destination + * Based on code of javalia: + * http://forums.alliedmods.net/showthread.php?t=159895 + * + * @param source Input file + * @param destination Output file + */ +stock bool:File_Copy(const String:source[], const String:destination[]) +{ + new Handle:file_source = OpenFile(source, "rb"); + + if (file_source == INVALID_HANDLE) { + return false; + } + + new Handle:file_destination = OpenFile(destination, "wb"); + + if (file_destination == INVALID_HANDLE) { + CloseHandle(file_source); + return false; + } + + new buffer[32]; + new cache; + + while (!IsEndOfFile(file_source)) { + cache = ReadFile(file_source, buffer, 32, 1); + WriteFile(file_destination, buffer, cache, 1); + } + + CloseHandle(file_source); + CloseHandle(file_destination); + + return true; +} diff --git a/gameserver/addons/sourcemod/scripting/disabled/timer-navcopy.sp b/gameserver/addons/sourcemod/scripting/disabled/timer-navcopy.sp new file mode 100644 index 0000000..75175af --- /dev/null +++ b/gameserver/addons/sourcemod/scripting/disabled/timer-navcopy.sp @@ -0,0 +1,73 @@ +#pragma semicolon 1 + +#include + +public OnPluginStart() +{ + CreateNavFiles(); +} + +public CreateNavFiles() +{ + new String:DestFile[256]; + new String:SourceFile[256]; + Format(SourceFile, sizeof(SourceFile), "maps/replay_bot.nav"); + if (!FileExists(SourceFile)) + { + LogError("Failed to create .nav files. Reason: %s doesn't exist!", SourceFile); + return; + } + + new Handle:hDir = OpenDirectory("maps"); + if(hDir == INVALID_HANDLE) + return; + + new String:sFile[64], FileType:fileType; + while(ReadDirEntry(hDir, sFile, sizeof(sFile), fileType)) + { + switch(fileType) + { + case FileType_File: + { + if(StrContains(sFile, ".bsp") != -1) + { + ReplaceString(sFile, sizeof(sFile), ".bsp", ""); + Format(DestFile, sizeof(DestFile), "maps/%s.nav", sFile); + if (!FileExists(DestFile)) + File_Copy(SourceFile, DestFile); + } + } + } + + } + CloseHandle(hDir); +} + +stock bool:File_Copy(const String:source[], const String:destination[]) +{ + new Handle:file_source = OpenFile(source, "rb"); + if (file_source == INVALID_HANDLE) + { + return false; + } + + new Handle:file_destination = OpenFile(destination, "wb"); + if (file_destination == INVALID_HANDLE) + { + CloseHandle(file_source); + return false; + } + + new buffer[32]; + new cache; + + while (!IsEndOfFile(file_source)) + { + cache = ReadFile(file_source, buffer, 32, 1); + WriteFile(file_destination, buffer, cache, 1); + } + + CloseHandle(file_source); + CloseHandle(file_destination); + return true; +} \ No newline at end of file diff --git a/gameserver/addons/sourcemod/scripting/timer-physics_fpsmax.sp b/gameserver/addons/sourcemod/scripting/disabled/timer-physics_fpsmax.sp similarity index 100% rename from gameserver/addons/sourcemod/scripting/timer-physics_fpsmax.sp rename to gameserver/addons/sourcemod/scripting/disabled/timer-physics_fpsmax.sp diff --git a/gameserver/addons/sourcemod/scripting/timer-physics_quakehop.sp b/gameserver/addons/sourcemod/scripting/disabled/timer-physics_quakehop.sp similarity index 100% rename from gameserver/addons/sourcemod/scripting/timer-physics_quakehop.sp rename to gameserver/addons/sourcemod/scripting/disabled/timer-physics_quakehop.sp diff --git a/gameserver/addons/sourcemod/scripting/timer-physics_realbhop_csgo.sp b/gameserver/addons/sourcemod/scripting/disabled/timer-physics_realbhop_csgo.sp similarity index 100% rename from gameserver/addons/sourcemod/scripting/timer-physics_realbhop_csgo.sp rename to gameserver/addons/sourcemod/scripting/disabled/timer-physics_realbhop_csgo.sp diff --git a/gameserver/addons/sourcemod/scripting/timer-physics_strafebooster.sp b/gameserver/addons/sourcemod/scripting/disabled/timer-physics_strafebooster.sp similarity index 100% rename from gameserver/addons/sourcemod/scripting/timer-physics_strafebooster.sp rename to gameserver/addons/sourcemod/scripting/disabled/timer-physics_strafebooster.sp diff --git a/gameserver/addons/sourcemod/scripting/timer-physics_thirdperson_csgo.sp b/gameserver/addons/sourcemod/scripting/disabled/timer-physics_thirdperson_csgo.sp similarity index 100% rename from gameserver/addons/sourcemod/scripting/timer-physics_thirdperson_csgo.sp rename to gameserver/addons/sourcemod/scripting/disabled/timer-physics_thirdperson_csgo.sp diff --git a/gameserver/addons/sourcemod/scripting/timer-weapons_css.sp b/gameserver/addons/sourcemod/scripting/disabled/timer-weapons_css.sp similarity index 100% rename from gameserver/addons/sourcemod/scripting/timer-weapons_css.sp rename to gameserver/addons/sourcemod/scripting/disabled/timer-weapons_css.sp diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/clients.inc b/gameserver/addons/sourcemod/scripting/include/smlib/clients.inc index 45a8c90..51a2fc6 100644 --- a/gameserver/addons/sourcemod/scripting/include/smlib/clients.inc +++ b/gameserver/addons/sourcemod/scripting/include/smlib/clients.inc @@ -44,6 +44,15 @@ * @param 2 CLIENTFILTER_ flags to check. */ #define LOOP_CLIENTS(%1,%2) for (new %1=Client_GetNext(%2); %1 >= 1 && %1 <= MaxClients; %1=Client_GetNext(%2, ++%1)) + +/** + * Macro for iterating trough all observers of a player. + * + * @param 1 Client Index for who to get the observers. + * @param 2 Name of the observer client index variable (will be only valid in the loop). + * @param 3 CLIENTFILTER_ flags to check. + */ +#define LOOP_OBSERVERS(%1,%2,%3) for (new %2=Client_GetNextObserver(%1, 1, %3); %2 >= 1 && %2 <= MaxClients; %2=Client_GetNextObserver(%1, ++%2, %3)) /** * Very useful macro to iterate all weapons of a client. @@ -171,7 +180,7 @@ stock Client_FindBySteamId(const String:auth[]) */ stock Client_FindByName(const String:name[], bool:partOfName=true, bool:caseSensitive=false) { - new String:clientName[MAX_STEAMAUTH_LENGTH]; + new String:clientName[MAX_NAME_LENGTH]; for (new client=1; client <= MaxClients; client++) { if (!IsClientAuthorized(client)) { continue; @@ -305,9 +314,9 @@ stock bool:Client_SetObserverMode(client, Obs_Mode:mode, bool:updateMoveType=tru * @param client Client Index. * @return Last Observer mode */ -stock Obs_mode:Client_GetObserverLastMode(client) +stock Obs_Mode:Client_GetObserverLastMode(client) { - return Obs_mode:GetEntProp(client, Prop_Data, "m_iObserverLastMode"); + return Obs_Mode:GetEntProp(client, Prop_Data, "m_iObserverLastMode"); } /** @@ -487,13 +496,29 @@ stock bool:Client_ScreenFade(client, duration, mode, holdtime=-1, r=0, g=0, b=0, return false; } - BfWriteShort(userMessage, duration); // Fade duration - BfWriteShort(userMessage, holdtime); // Fade hold time - BfWriteShort(userMessage, mode); // What to do - BfWriteByte(userMessage, r); // Color R - BfWriteByte(userMessage, g); // Color G - BfWriteByte(userMessage, b); // Color B - BfWriteByte(userMessage, a); // Color Alpha + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && + GetUserMessageType() == UM_Protobuf) { + + new color[4]; + color[0] = r; + color[1] = g; + color[2] = b; + color[3] = a; + + PbSetInt(userMessage, "duration", duration); + PbSetInt(userMessage, "hold_time", holdtime); + PbSetInt(userMessage, "flags", mode); + PbSetColor(userMessage, "clr", color); + } + else { + BfWriteShort(userMessage, duration); // Fade duration + BfWriteShort(userMessage, holdtime); // Fade hold time + BfWriteShort(userMessage, mode); // What to do + BfWriteByte(userMessage, r); // Color R + BfWriteByte(userMessage, g); // Color G + BfWriteByte(userMessage, b); // Color B + BfWriteByte(userMessage, a); // Color Alpha + } EndMessage(); return true; @@ -626,9 +651,9 @@ stock Client_GetCount(bool:countInGameOnly=true, bool:countFakeClients=true) * The Scoreboard uses the goldSource corrected Ping, the net_graph doesn't * For Fake Clients 0 is returned. * - * @param inGameOnly Wether players not ingame yet are also counted - * @param countBots If true bots will be counted too. - * @return Client's ping or 0 for fake clients + * @param client Client index + * @param goldSource If true, get the ping as displayed in the player's scoreboard, false returns the net_graph variant. + * @return Client's fake ping or 0 for fake clients */ stock Client_GetFakePing(client, bool:goldSource=true) { @@ -890,10 +915,20 @@ stock bool:Client_RawAudio(client, const emitter, const String:soundfile[], Floa return false; } - BfWriteByte(message, pitch); - BfWriteByte(message, emitter); - BfWriteFloat(message, length); - BfWriteString(message, soundfile); + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetInt(message, "pitch", pitch); + PbSetInt(message, "entidx", emitter); + PbSetFloat(message, "duration", length ); + PbSetString(message, "voice_filename", soundfile); + } + else { + BfWriteByte(message, pitch); + BfWriteByte(message, emitter); + BfWriteFloat(message, length); + BfWriteString(message, soundfile); + } EndMessage(); return true; @@ -918,10 +953,20 @@ stock bool:Client_RawAudioToAll(const emitter, const String:soundfile[], Float:l return false; } - BfWriteByte(message, pitch); - BfWriteByte(message, emitter); - BfWriteFloat(message, length); - BfWriteString(message, soundfile); + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetInt(message, "pitch", pitch); + PbSetInt(message, "entidx", emitter); + PbSetFloat(message, "duration", length); + PbSetString(message, "voice_filename", soundfile); + } + else { + BfWriteByte(message, pitch); + BfWriteByte(message, emitter); + BfWriteFloat(message, length); + BfWriteString(message, soundfile); + } EndMessage(); return true; @@ -1323,11 +1368,11 @@ stock Client_HasWeapon(client, const String:className[]) stock Client_GetWeapon(client, const String:className[]) { new offset = Client_GetWeaponsOffset(client) - 4; - + new weapon = INVALID_ENT_REFERENCE; for (new i=0; i < MAX_WEAPONS; i++) { offset += 4; - - new weapon = GetEntDataEnt2(client, offset); + + weapon = GetEntDataEnt2(client, offset); if (!Weapon_IsValid(weapon)) { continue; @@ -1337,7 +1382,7 @@ stock Client_GetWeapon(client, const String:className[]) return weapon; } } - + return INVALID_ENT_REFERENCE; } @@ -1521,6 +1566,30 @@ stock bool:Client_GetWeaponPlayerAmmo(client, const String:className[], &primary return true; } +/** + * Gets the primary and secondary ammo the player carries for a specific weapon index. + * + * @param client Client Index. + * @param weapon Weapon Entity Index. + * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched. + * @param secondaryAmmo Secondary ammo stock value from the client, if -1 the value is untouched. + * @noreturn + */ +stock Client_GetWeaponPlayerAmmoEx(client, weapon, &primaryAmmo=-1, &secondaryAmmo=-1) +{ + new offset_ammo = FindDataMapOffs(client, "m_iAmmo"); + + if (primaryAmmo != -1) { + new offset = offset_ammo + (Weapon_GetPrimaryAmmoType(weapon) * 4); + primaryAmmo = GetEntData(client, offset); + } + + if (secondaryAmmo != -1) { + new offset = offset_ammo + (Weapon_GetSecondaryAmmoType(weapon) * 4); + secondaryAmmo = GetEntData(client, offset); + } +} + /** * Sets the primary and secondary ammo the player carries for a specific weapon classname. * @@ -1586,7 +1655,12 @@ stock Client_SetWeaponAmmo(client, const String:className[], primaryAmmo=-1, sec return false; } - Weapon_SetClips(weapon, primaryClip, secondaryClip); + if (primaryClip != -1) { + Weapon_SetPrimaryClip(weapon, primaryClip); + } + if (secondaryClip != -1) { + Weapon_SetSecondaryClip(weapon, secondaryClip); + } Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo, secondaryAmmo); return true; @@ -1642,8 +1716,16 @@ stock bool:Client_PrintHintText(client, const String:format[], any:...) SetGlobalTransTarget(client); VFormat(buffer, sizeof(buffer), format, 3); - BfWriteByte(userMessage, 1); - BfWriteString(userMessage, buffer); + + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetString(userMessage, "text", format); + } + else { + BfWriteByte(userMessage, 1); + BfWriteString(userMessage, buffer); + } EndMessage(); @@ -1698,8 +1780,15 @@ stock bool:Client_PrintKeyHintText(client, const String:format[], any:...) SetGlobalTransTarget(client); VFormat(buffer, sizeof(buffer), format, 3); - BfWriteByte(userMessage, 1); - BfWriteString(userMessage, buffer); + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetString(userMessage, "hints", buffer); + } + else { + BfWriteByte(userMessage, 1); + BfWriteString(userMessage, buffer); + } EndMessage(); @@ -1767,17 +1856,43 @@ stock Client_PrintToChatRaw(client, const String:message[], subject=0, bool:isCh if (sayText2_supported) { userMessage = StartMessageOne("SayText2", client, USERMSG_RELIABLE); - BfWriteByte(userMessage , subject); - BfWriteByte(userMessage , isChat); - BfWriteString(userMessage , message); + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetInt(userMessage, "ent_idx", subject); + PbSetBool(userMessage, "chat", isChat); + PbSetString(userMessage, "msg_name", message); + + // psychonic: Furthermore, some usermessages with repeated field, + // such as the commonly-used SayText2, expected an undocumented + // specific number of values added, else the client will crash when receiving. + PbAddString(userMessage, "params", ""); + PbAddString(userMessage, "params", ""); + PbAddString(userMessage, "params", ""); + PbAddString(userMessage, "params", ""); + } + else { + BfWriteByte(userMessage , subject); + BfWriteByte(userMessage , isChat); + BfWriteString(userMessage , message); + } } else { userMessage = StartMessageOne("SayText", client, USERMSG_RELIABLE); - BfWriteByte(userMessage , subject); - BfWriteString(userMessage , message); - // For DoD:S nickname coloring - BfWriteByte(userMessage , -1); + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetInt(userMessage, "ent_idx", subject); + PbSetString(userMessage, "text", message); + PbSetBool(userMessage, "chat", isChat); + } + else { + BfWriteByte(userMessage , subject); + BfWriteString(userMessage , message); + // For DoD:S nickname coloring + BfWriteByte(userMessage , -1); + } } EndMessage(); @@ -1979,8 +2094,7 @@ stock Client_Print(client, ClientHudPrint:destination, const String:format[], an (destination != ClientHudPrint_Console) || (destination == ClientHudPrint_Console && GuessSDKVersion() < SOURCE_SDK_LEFT4DEAD)) { - Color_StripFromChatText(buffer, buffer2, sizeof(buffer2)); - strcopy(buffer, sizeof(buffer), buffer2); + Color_StripFromChatText(buffer2, buffer2, sizeof(buffer2)); if (client == 0) { PrintToServer(buffer2); @@ -1991,8 +2105,20 @@ stock Client_Print(client, ClientHudPrint:destination, const String:format[], an new Handle:userMessage = INVALID_HANDLE; userMessage = StartMessageOne("TextMsg", client, USERMSG_RELIABLE); - BfWriteByte(userMessage , _:ClientHudPrint_Console); - BfWriteString(userMessage , buffer); + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetInt(userMessage, "msg_dst", _:destination); + PbAddString(userMessage, "params", buffer2); + PbAddString(userMessage, "params", ""); + PbAddString(userMessage, "params", ""); + PbAddString(userMessage, "params", ""); + PbAddString(userMessage, "params", ""); + } + else { + BfWriteByte(userMessage , _:destination); + BfWriteString(userMessage , buffer2); + } EndMessage(); } @@ -2043,23 +2169,34 @@ stock Client_Reply(client, const String:format[], any:...) */ stock bool:Client_Shake(client, command=SHAKE_START, Float:amplitude=50.0, Float:frequency=150.0, Float:duration=3.0) { + if (command == SHAKE_STOP) { + amplitude = 0.0; + } + else if (amplitude <= 0.0) { + return false; + } + new Handle:userMessage = StartMessageOne("Shake", client); if (userMessage == INVALID_HANDLE) { return false; } - if (command == SHAKE_STOP) { - amplitude = 0.0; + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available + && GetUserMessageType() == UM_Protobuf) { + + PbSetInt(userMessage, "command", command); + PbSetFloat(userMessage, "local_amplitude", amplitude); + PbSetFloat(userMessage, "frequency", frequency); + PbSetFloat(userMessage, "duration", duration); } - else if (amplitude <= 0.0) { - return false; + else { + BfWriteByte(userMessage, command); // Shake Command + BfWriteFloat(userMessage, amplitude); // shake magnitude/amplitude + BfWriteFloat(userMessage, frequency); // shake noise frequency + BfWriteFloat(userMessage, duration); // shake lasts this long } - - BfWriteByte(userMessage, command); // Shake Command - BfWriteFloat(userMessage, amplitude); // shake magnitude/amplitude - BfWriteFloat(userMessage, frequency); // shake noise frequency - BfWriteFloat(userMessage, duration); // shake lasts this long + EndMessage(); return true; @@ -2172,7 +2309,7 @@ stock bool:Client_IsLookingAtWall(client, Float:distance=40.0) { TR_GetEndPosition(posEnd, trace); - if (GetVectorDistance(posEye, posEnd) <= distance) { + if (GetVectorDistance(posEye, posEnd, true) <= (distance * distance)) { isClientLookingAtWall = true; } } @@ -2210,19 +2347,20 @@ stock Client_GetClass(client) * Other games maybe work too, but are not tested. * * @param client Client Index. + * @param playerClass The class number to set the player to. Depends on game. * @param persistant If true changes the players desired class so the change stays after death (probably TF2 only). * @return Class Index. */ -stock Client_SetClass(client, class, bool:persistant=false) +stock Client_SetClass(client, playerClass, bool:persistant=false) { if (GuessSDKVersion() == SOURCE_SDK_DARKMESSIAH) { - GetEntProp(client, Prop_Send, "m_iPlayerClass"); + SetEntProp(client, Prop_Send, "m_iPlayerClass", playerClass); } else { - SetEntProp(client, Prop_Send, "m_iClass", class); + SetEntProp(client, Prop_Send, "m_iClass", playerClass); if (persistant) { - SetEntProp(client, Prop_Send, "m_iDesiredPlayerClass", class); + SetEntProp(client, Prop_Send, "m_iDesiredPlayerClass", playerClass); } } } @@ -2526,7 +2664,7 @@ stock bool:Client_MatchesFilter(client, flags) /** * Gets all clients matching the specified flags filter. * - * @param Client Client Array, size should be MaxClients or MAXPLAYERS + * @param client Client Array, size should be MaxClients or MAXPLAYERS * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). * @return The number of clients stored in the array */ @@ -2600,3 +2738,383 @@ stock Float:Client_GetMapTime(client) return (fClientTime < fGameTime) ? fClientTime : fGameTime; } + +/** + * Gets client money value (for games like Counter-Strike:Source). + * + * @param client Client Index. + * @return Money value from the client. + */ +stock Client_GetMoney(client) +{ + return GetEntProp(client, Prop_Send, "m_iAccount"); +} + +/** + * Sets client money value (for games like Counter-Strike:Source). + * + * @param client Client Index. + * @param value Money value to set. + * @noreturn + */ +stock Client_SetMoney(client, value) +{ + SetEntProp(client, Prop_Send, "m_iAccount", value); +} + +/** + * Gets a client's observers. + * + * @param client Client Index. + * @param observers Array with size of MaxClients or MAXPLAYERS. + * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). + * @return Number of observers found. + */ +stock Client_GetObservers(client, observers[], flags=CLIENTFILTER_ALL) +{ + new count = 0; + + LOOP_CLIENTS(player, CLIENTFILTER_OBSERVERS | flags) { + + if (Client_GetObserverTarget(player) == client) { + observers[count++] = player; + } + } + + return count; +} + +static Float:getPlayersInRadius_distances[MAXPLAYERS+1]; + +/** + * Gets all players near a player in a certain radius and + * orders the players by distance (optional). + * + * @param client Client Index. + * @param clients Array with size of MaxClients or MAXPLAYERS. + * @param radius radius Float (max distance) + * @param orderByDistance Set to true to order the clients by distance, false otherwise. + * @return Number of clients found. + */ +stock Client_GetPlayersInRadius(client, clients[], Float:radius, bool:orderByDistance=true) +{ + decl Float:origin_client[3]; + new + Float:distance, + count=0; + + Entity_GetAbsOrigin(client, origin_client); + + LOOP_CLIENTS(player, CLIENTFILTER_INGAME) { + + if (player == client) { + continue; + } + + distance = Entity_GetDistanceOrigin(player, origin_client); + + if (distance <= radius) { + clients[count++] = player; + + if (orderByDistance) { + getPlayersInRadius_distances[player] = distance; + } + } + } + + if (orderByDistance) { + SortCustom1D(clients, count, __smlib_GetPlayersInRadius_Sort); + } + + return count; +} + +public __smlib_GetPlayersInRadius_Sort(player1, player2, const clients[], Handle:hndl) +{ + return FloatCompare(getPlayersInRadius_distances[player1], getPlayersInRadius_distances[player2]); +} + +/** + * Gets the next player observing client starting at start. + * + * @param client Client Index (Observer Target) + * @param start Start Index. + * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). + * @return Client Index or -1 if no client was found + */ +stock Client_GetNextObserver(client, start=1, flags=CLIENTFILTER_ALL) +{ + for (new player=start; player <= MaxClients; player++) { + + if (Client_MatchesFilter(player, CLIENTFILTER_OBSERVERS | flags)) { + + if (Client_GetObserverTarget(player) == client) { + return player; + } + } + } + + return -1; +} + +/** + * Searchs and returns the game's player_manager entity. + * This should be called on every map start. + * + * @return player_manager entity or INVALID_ENT_REFERENCE if not found. + */ +stock Client_GetPlayerManager() +{ + static player_manager = INVALID_ENT_REFERENCE; + + if (player_manager != INVALID_ENT_REFERENCE) { + + if (Entity_IsValid(player_manager)) { + return player_manager; + } + else { + player_manager = INVALID_ENT_REFERENCE; + } + } + + new maxEntities = GetMaxEntities(); + + for (new entity=0; entity < maxEntities; entity++) { + + if (!Entity_IsValid(entity)) { + continue; + } + + if (Entity_ClassNameMatches(entity, "player_manager", true)) { + player_manager = EntIndexToEntRef(entity); + + return player_manager; + } + } + + return INVALID_ENT_REFERENCE; +} + +/** + * Sets the client's ping as displayed in the scoreboards. + * Should be called OnGameFrame. + * + * @param client Client Index + * @param start New ping value. + * @return True on sucess, false otherwise. + */ +stock Client_SetPing(client, value) +{ + new player_manager = Client_GetPlayerManager(); + + static offset = -1; + + if (offset== -1) { + offset = GetEntSendPropOffs(player_manager, "m_iPing", true); + + if (offset == -1) { + return false; + } + } + + SetEntData(player_manager, offset + (client * 4), value, 4, true); + + return true; +} + +static printToTop_excludeclient = -1; + +/** + * Exclude a client from the next call to a Client_PrintToTop function. + * + * @param client Client Index. + * @noreturn + */ +stock Client_PrintToTopExclude(client) +{ + printToTop_excludeclient = client; +} + +/** + * Prints colored text to the top left of the screen + * for one client. Does not work in all games. + * Line Breaks can't be done. + * + * @param client Client Index. + * @param r Red amount. + * @param g Green amount. + * @param b Blue amount. + * @param a Transparency. + * @param duration Duration in seconds the text stays (min 10 - max 200 seconds). + * @param text Text to print to. + * @return True on success, false if the key value for the dialog couldn't be created or closed. + */ +stock bool:Client_PrintToTopRaw(client, r=255, g=255, b=255, a=255, Float:duration=10.0, const String:text[]) +{ + //message line max 50 + //overline: 39*_ + //underline: 44*T + new Handle:keyValue = CreateKeyValues("Stuff", "title", text); + + if (keyValue == INVALID_HANDLE) { + return false; + } + + KvSetColor(keyValue, "color", r, g, b, a); + KvSetNum(keyValue, "level", 1); + KvSetNum(keyValue, "time", RoundToFloor(duration)); + + CreateDialog(client, keyValue, DialogType_Msg); + + if (!CloseHandle(keyValue)) { + return false; + } + return true; +} + +/** + * Prints colored text to the top left of the screen + * for one client. Does not work in all games. + * Line Breaks can't be done. + * + * @param client Client Index. + * @param r Red amount. + * @param g Green amount. + * @param b Blue amount. + * @param a Transparency. + * @param duration Duration in seconds the text stays (min 10 - max 200 seconds). + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @return True on success, false if the key value for the dialog couldn't be created or closed. + */ +stock bool:Client_PrintToTop(client, r=255, g=255, b=255, a=255, Float:duration=10.0, const String:format[], any:...) +{ + new String:buffer[150]; + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 8); + + return Client_PrintToTopRaw(client, r, g, b, a, duration, buffer); +} + +/** + * Prints colored text to the top left of the screen + * to all clients. Does not work in all games. + * Line Breaks can't be done. + * + * @param r Red amount. + * @param g Green amount. + * @param b Blue amount. + * @param a Transparency. + * @param duration Duration in seconds the text stays (min 10 - max 200 seconds). + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + */ +stock Client_PrintToTopAll(r=255, g=255, b=255, a=255, Float:duration=10.0, const String:format[], any:...) +{ + decl + String:buffer[150]; + new + language, + lastLanguage = -1; + + for (new client=1; client <= MaxClients; client++) { + + if (!IsClientInGame(client)) { + continue; + } + + if (client == printToTop_excludeclient) { + printToTop_excludeclient = -1; + continue; + } + + language = GetClientLanguage(client); + + if (language != lastLanguage) { + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 7); + + lastLanguage = language; + } + + Client_PrintToTopRaw(client, r, g, b, a, duration, buffer); + } +} + +/** + * Prints colored text to the top left of the screen + * to specified clients. Does not work in all games. + * Line Breaks can't be done. + * + * @param clients Client Array. + * @param numClients Number of clients in the clients array. + * @param r Red amount. + * @param g Green amount. + * @param b Blue amount. + * @param a Transparency. + * @param duration Duration in seconds the text stays (min 10 - max 200 seconds). + * @param format Formatting rules. + * @param ... Variable number of format parameters. + * @noreturn + */ +stock Client_PrintToTopEx(clients[], numClients, r=255, g=255, b=255, a=255, Float:duration=10.0, const String:format[], any:...) +{ + decl + String:buffer[150]; + new + client, + language, + lastLanguage = -1; + + for (new i=0; i < numClients; i++) { + + client = clients[i]; + + if (!IsClientInGame(client)) { + continue; + } + + if (client == printToTop_excludeclient) { + printToTop_excludeclient = -1; + continue; + } + + language = GetClientLanguage(client); + + if (language != lastLanguage) { + SetGlobalTransTarget(client); + VFormat(buffer, sizeof(buffer), format, 9); + + lastLanguage = language; + } + + Client_PrintToTopRaw(client, r, g, b, a, duration, buffer); + } +} + +/** + * Opens the scoreboard for a specific client + * + * @tested csgo + * @param client Client index + * @noreturn + */ +stock Client_ShowScoreboard(client, flags=USERMSG_RELIABLE | USERMSG_BLOCKHOOKS) +{ + new Handle:handle = StartMessageOne("VGUIMenu", client, flags); + + if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && + GetUserMessageType() == UM_Protobuf) { + + PbSetString(handle, "name", "scores"); + PbSetBool(handle, "show", true); + } + else { + BfWriteString(handle, "scores"); + BfWriteByte(handle, 1); // Show + BfWriteByte(handle, 0); // subkeys count + } + + EndMessage(); +} diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/colors.inc b/gameserver/addons/sourcemod/scripting/include/smlib/colors.inc index dcc982e..357d5d3 100644 --- a/gameserver/addons/sourcemod/scripting/include/smlib/colors.inc +++ b/gameserver/addons/sourcemod/scripting/include/smlib/colors.inc @@ -109,6 +109,16 @@ stock Color_ChatSetSubject(client) chatSubject = client; } +/** + * Gets the subject used for the chat color parser. + * + * @return Client Index/Subject, or CHATCOLOR_NOSUBJECT if none + */ +stock Color_ChatGetSubject() +{ + return chatSubject; +} + /** * Clears the subject used for the chat color parser. * Call this after Color_ParseChatText(). @@ -126,23 +136,27 @@ stock Color_ChatClearSubject() * table. The support colors are hardcoded, but can be overriden for each game by * creating the file gamedata/smlib_colors.games.txt. * - * @param str Chat String. + * @param str Chat String * @param subject Output Buffer * @param size Output Buffer size - * return + * @return Returns a value for the subject */ stock Color_ParseChatText(const String:str[], String:buffer[], size) { new bool:inBracket = false, x = 0, x_buf = 0, x_tag = 0, - currentColor = '\x01', // Initialize with normal color - code = -1, subject = CHATCOLOR_NOSUBJECT; - decl String:sTag[4] = ""; + decl + String:sTag[10] = "", // This should be able to hold "\x08RRGGBBAA"\0 + String:colorCode[10] = "", // This should be able to hold "\x08RRGGBBAA"\0 + String:currentColor[10] = "\x01"; // Initialize with normal color size--; + + // Every chat message has to start with a + // color code, otherwise it will ignore all colors. buffer[x_buf++] = '\x01'; while (str[x] != '\0') { @@ -154,25 +168,44 @@ stock Color_ParseChatText(const String:str[], String:buffer[], size) new char = str[x++]; if (inBracket) { - if (char == '}' || x_tag > 2) { - inBracket = false; + // We allow up to 9 characters in the tag (#RRGGBBAA) + if (char == '}' || x_tag > 9) { + inBracket = false; sTag[x_tag] = '\0'; - x_tag = 0; - + x_tag = 0; + if (char == '}') { - code = Color_TagToCode(sTag, subject); - if (code == 0) { - buffer[x_buf+1] = '\0'; + Color_TagToCode(sTag, subject, colorCode); + + if (colorCode[0] == '\0') { + // We got an unknown tag, ignore this + // and forward it to the buffer. + + // Terminate buffer with \0 so Format can handle it. + buffer[x_buf] = '\0'; x_buf = Format(buffer, size, "%s{%s}", buffer, sTag); + + // We 'r done here continue; } - else if (code != currentColor) { - buffer[x_buf++] = code; - currentColor = code; + else if (!StrEqual(colorCode, currentColor)) { + // If we are already using this color, + // we don't need to set it again. + + // Write the color code to our buffer. + // x_buf will be increased by the number of cells written. + x_buf += strcopy(buffer[x_buf], size - x_buf, colorCode); + + // Remember the current color. + strcopy(currentColor, sizeof(currentColor), colorCode); } } else { - buffer[x_buf+1] = '\0'; + // If the tag character limit exceeds 9, + // we have to do something. + + // Terminate buffer with \0 so Format can handle it. + buffer[x_buf] = '\0'; x_buf = Format(buffer, size, "%s{%s%c", buffer, sTag, char); } } @@ -192,6 +225,13 @@ stock Color_ParseChatText(const String:str[], String:buffer[], size) } } + // Write remaining text to the buffer, + // if we have been inside brackets. + if (inBracket) { + buffer[x_buf] = '\0'; + x_buf = Format(buffer, size, "%s{%s", buffer, sTag); + } + buffer[x_buf] = '\0'; return subject; @@ -202,18 +242,63 @@ stock Color_ParseChatText(const String:str[], String:buffer[], size) * * @param tag Color Tag String. * @param subject Subject variable to pass - * @return Chat Color Code char or 0 if the tag couldn't be found. + * @param result The result as character sequence (string). This will be \0 if the tag is unkown. + * @noreturn */ -stock Color_TagToCode(const String:tag[], &subject=-1) { - new n = Array_FindString(chatColorTags, sizeof(chatColorTags), tag); +stock Color_TagToCode(const String:tag[], &subject=-1, String:result[10]) +{ + // Check if the tag starts with a '#'. + // We will handle it has RGB(A)-color code then. + if (tag[0] == '#') { + new length_tag = strlen(tag); + switch (length_tag - 1) { + // #RGB -> \07RRGGBB + case 3: { + FormatEx( + result, sizeof(result), "\x07%c%c%c%c%c%c", + tag[1], tag[1], tag[2], tag[2], tag[3], tag[3] + ); + } + // #RGBA -> \08RRGGBBAA + case 4: { + FormatEx( + result, sizeof(result), "\x08%c%c%c%c%c%c%c%c", + tag[1], tag[1], tag[2], tag[2], tag[3], tag[3], tag[4], tag[4] + ); + } + // #RRGGBB -> \07RRGGBB + case 6: { + FormatEx(result, sizeof(result), "\x07%s", tag[1]); + } + // #RRGGBBAA -> \08RRGGBBAA + case 8: { + FormatEx(result, sizeof(result), "\x08%s", tag[1]); + } + default: { + result[0] = '\0'; + } + } - if (n == -1) { - return 0; + return; } + else { + // Try to handle this string as color name + new n = Array_FindString(chatColorTags, sizeof(chatColorTags), tag); + + // Check if this tag is invalid + if (n == -1) { + result[0] = '\0'; + return; + } - Color_GetChatColorInfo(n, subject); + // Check if the color is actually supported 'n stuff. + Color_GetChatColorInfo(n, subject); - return chatColorInfo[n][ChatColorInfo_Code]; + result[0] = chatColorInfo[n][ChatColorInfo_Code]; + result[1] = '\0'; + } + + return; } /** @@ -245,6 +330,15 @@ stock Color_StripFromChatText(const String:input[], String:output[], size) output[x] = '\0'; } +/** + * Checks the gamename and sets default values. + * For example if some colors are supported, or + * if a game uses another color code for a specific color. + * All those hardcoded default values can be overriden in + * smlib's color gamedata file. + * + * @noreturn + */ static stock Color_ChatInitialize() { static initialized = false; @@ -258,7 +352,7 @@ static stock Color_ChatInitialize() decl String:gameFolderName[32]; GetGameFolderName(gameFolderName, sizeof(gameFolderName)); - chatColorInfo[ChatColor_Black][ChatColorInfo_Supported] = false; + chatColorInfo[ChatColor_Black][ChatColorInfo_Supported] = false; if (strncmp(gameFolderName, "left4dead", 9, false) != 0 && !StrEqual(gameFolderName, "cstrike", false) && @@ -348,6 +442,15 @@ static stock Color_ChatInitialize() mp_teamplay = FindConVar("mp_teamplay"); } +/** + * Checks if the passed color index is actually supported + * for the current game. If not, the index will be overwritten + * The color resolving works recursively until a valid color is found. + * + * @param index + * @param subject A client index or CHATCOLOR_NOSUBJECT + * @noreturn + */ static stock Color_GetChatColorInfo(&index, &subject=CHATCOLOR_NOSUBJECT) { Color_ChatInitialize(); diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/edicts.inc b/gameserver/addons/sourcemod/scripting/include/smlib/edicts.inc index 5974939..7b719aa 100644 --- a/gameserver/addons/sourcemod/scripting/include/smlib/edicts.inc +++ b/gameserver/addons/sourcemod/scripting/include/smlib/edicts.inc @@ -67,7 +67,7 @@ stock Edict_FindByHammerId(hammerId) stock Edict_GetClosest(Float:vecOrigin_center[3], bool:clientsOnly=false, ignoreEntity=-1) { decl Float:vecOrigin_edict[3]; - new Float:distance = 0.0; + new Float:smallestDistance = 0.0; new closestEdict = INVALID_ENT_REFERENCE; new maxEntities; @@ -95,10 +95,10 @@ stock Edict_GetClosest(Float:vecOrigin_center[3], bool:clientsOnly=false, ignore Entity_GetAbsOrigin(edict, vecOrigin_edict); - new Float:edict_distance = GetVectorDistance(vecOrigin_center, vecOrigin_edict); + new Float:edict_distance = GetVectorDistance(vecOrigin_center, vecOrigin_edict, true); - if (edict_distance < distance) { - distance = edict_distance; + if (edict_distance < smallestDistance || smallestDistance == 0.0) { + smallestDistance = edict_distance; closestEdict = edict; } } diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/effects.inc b/gameserver/addons/sourcemod/scripting/include/smlib/effects.inc index cefe9f9..98cd5a9 100644 --- a/gameserver/addons/sourcemod/scripting/include/smlib/effects.inc +++ b/gameserver/addons/sourcemod/scripting/include/smlib/effects.inc @@ -12,6 +12,8 @@ #include #include + + // Entity Dissolve types enum DissolveType { @@ -26,9 +28,10 @@ enum DissolveType * * @param client Client Index. * @param dissolveType Dissolve Type, use the DissolveType enum. + * @param magnitude How strongly to push away from the center. * @return True on success, otherwise false. */ -stock bool:Effect_DissolveEntity(entity, DissolveType:dissolveType=DISSOLVE_NORMAL) +stock bool:Effect_DissolveEntity(entity, DissolveType:dissolveType=DISSOLVE_NORMAL, magnitude=1) { new env_entity_dissolver = CreateEntityByName("env_entity_dissolver"); @@ -38,6 +41,7 @@ stock bool:Effect_DissolveEntity(entity, DissolveType:dissolveType=DISSOLVE_NORM Entity_PointAtTarget(env_entity_dissolver, entity); SetEntProp(env_entity_dissolver, Prop_Send, "m_nDissolveType", _:dissolveType); + SetEntProp(env_entity_dissolver, Prop_Send, "m_nMagnitude", magnitude); AcceptEntityInput(env_entity_dissolver, "Dissolve"); Entity_Kill(env_entity_dissolver); @@ -261,7 +265,7 @@ stock Effect_DrawBeamBoxToAll( * * Ported from eventscripts vecmath library. * - * @param clients An array of clients to show the box to. + * @param clients An array of clients to show the box to. * @param numClients Number of players in the array. * @param bottomCorner One bottom corner of the box. * @param upperCorner One upper corner of the box. @@ -304,9 +308,11 @@ stock Effect_DrawBeamBox( } corners[1][0] = upperCorner[0]; - corners[2][0] = upperCorner[0]; corners[2][1] = upperCorner[1]; + corners[2][0] = upperCorner[0]; + corners[2][1] = upperCorner[1]; corners[3][1] = upperCorner[1]; - corners[4][0] = bottomCorner[0]; corners[4][1] = bottomCorner[1]; + corners[4][0] = bottomCorner[0]; + corners[4][1] = bottomCorner[1]; corners[5][1] = bottomCorner[1]; corners[7][0] = bottomCorner[0]; @@ -333,3 +339,397 @@ stock Effect_DrawBeamBox( TE_Send(clients, numClients); } } + + +/** + * Sends a boxed beam effect to one player. + * + * Ported from eventscripts vecmath library. + * + * @param client The client to show the box to. + * @param origin Origin/center of the box. + * @param mins Min size Vector + * @param maxs Max size Vector + * @param angles Angles used to rotate the box. + * @param modelIndex Precached model index. + * @param haloIndex Precached model index. + * @param startFrame Initital frame to render. + * @param frameRate Beam frame rate. + * @param life Time duration of the beam. + * @param width Initial beam width. + * @param endWidth Final beam width. + * @param fadeLength Beam fade time duration. + * @param amplitude Beam amplitude. + * @param color Color array (r, g, b, a). + * @param speed Speed of the beam. + * @noreturn + */ +stock Effect_DrawBeamBoxRotatableToClient( + client, + const Float:origin[3], + const Float:mins[3], + const Float:maxs[3], + const Float:angles[3], + modelIndex, + haloIndex, + startFrame=0, + frameRate=30, + Float:life=5.0, + Float:width=5.0, + Float:endWidth=5.0, + fadeLength=2, + Float:amplitude=1.0, + const color[4]={ 255, 0, 0, 255 }, + speed=0 +) { + new clients[1]; + clients[0] = client; + Effect_DrawBeamBoxRotatable(clients, 1, origin, mins, maxs, angles, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); +} + + + +/** + * Sends a boxed beam effect to all players. + * + * Ported from eventscripts vecmath library. + * + * @param origin Origin/center of the box. + * @param mins Min size Vector + * @param maxs Max size Vector + * @param angles Angles used to rotate the box. + * @param modelIndex Precached model index. + * @param haloIndex Precached model index. + * @param startFrame Initital frame to render. + * @param frameRate Beam frame rate. + * @param life Time duration of the beam. + * @param width Initial beam width. + * @param endWidth Final beam width. + * @param fadeLength Beam fade time duration. + * @param amplitude Beam amplitude. + * @param color Color array (r, g, b, a). + * @param speed Speed of the beam. + * @noreturn + */ +stock Effect_DrawBeamBoxRotatableToAll( + const Float:origin[3], + const Float:mins[3], + const Float:maxs[3], + const Float:angles[3], + modelIndex, + haloIndex, + startFrame=0, + frameRate=30, + Float:life=5.0, + Float:width=5.0, + Float:endWidth=5.0, + fadeLength=2, + Float:amplitude=1.0, + const color[4]={ 255, 0, 0, 255 }, + speed=0 +) +{ + new clients[MaxClients]; + new numClients = Client_Get(clients, CLIENTFILTER_INGAME); + + Effect_DrawBeamBoxRotatable(clients, numClients, origin, mins, maxs, angles, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); +} + +/** + * Sends a boxed beam effect to a list of players. + * + * Ported from eventscripts vecmath library. + * + * @param clients An array of clients to show the box to. + * @param numClients Number of players in the array. + * @param origin Origin/center of the box. + * @param mins Min size Vector + * @param maxs Max size Vector + * @param angles Angles used to rotate the box. + * @param modelIndex Precached model index. + * @param haloIndex Precached model index. + * @param startFrame Initital frame to render. + * @param frameRate Beam frame rate. + * @param life Time duration of the beam. + * @param width Initial beam width. + * @param endWidth Final beam width. + * @param fadeLength Beam fade time duration. + * @param amplitude Beam amplitude. + * @param color Color array (r, g, b, a). + * @param speed Speed of the beam. + * @noreturn + */ +stock Effect_DrawBeamBoxRotatable( + clients[], + numClients, + const Float:origin[3], + const Float:mins[3], + const Float:maxs[3], + const Float:angles[3], + modelIndex, + haloIndex, + startFrame=0, + frameRate=30, + Float:life=5.0, + Float:width=5.0, + Float:endWidth=5.0, + fadeLength=2, + Float:amplitude=1.0, + const color[4]={ 255, 0, 0, 255 }, + speed=0 +) { + // Create the additional corners of the box + decl Float:corners[8][3]; + Array_Copy(mins, corners[0], 3); + Math_MakeVector(maxs[0], mins[1], mins[2], corners[1]); + Math_MakeVector(maxs[0], maxs[1], mins[2], corners[2]); + Math_MakeVector(mins[0], maxs[1], mins[2], corners[3]); + Math_MakeVector(mins[0], mins[1], maxs[2], corners[4]); + Math_MakeVector(maxs[0], mins[1], maxs[2], corners[5]); + Array_Copy(maxs, corners[6], 3); + Math_MakeVector(mins[0], maxs[1], maxs[2], corners[7]); + + // Rotate all edges + for (new i=0; i < sizeof(corners); i++) { + Math_RotateVector(corners[i], angles, corners[i]); + } + + // Apply world offset (after rotation) + for (new i=0; i < sizeof(corners); i++) { + AddVectors(origin, corners[i], corners[i]); + } + + // Draw all the edges + // Horizontal Lines + // Bottom + for (new i=0; i < 4; i++) { + new j = ( i == 3 ? 0 : i+1 ); + TE_SetupBeamPoints(corners[i], corners[j], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); + TE_Send(clients, numClients); + } + + // Top + for (new i=4; i < 8; i++) { + new j = ( i == 7 ? 4 : i+1 ); + TE_SetupBeamPoints(corners[i], corners[j], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); + TE_Send(clients, numClients); + } + + // All Vertical Lines + for (new i=0; i < 4; i++) { + TE_SetupBeamPoints(corners[i], corners[i+4], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed); + TE_Send(clients, numClients); + } +} + +/** + * Displays the given axis of rotation as beam effect to one player. + * + * @param client The client to show the box to. + * @param origin Origin/center of the box. + * @param angles Angles used to rotate the box. + * @param length The length in each direction. + * @param modelIndex Precached model index. + * @param haloIndex Precached model index. + * @param startFrame Initital frame to render. + * @param frameRate Beam frame rate. + * @param life Time duration of the beam. + * @param width Initial beam width. + * @param endWidth Final beam width. + * @param fadeLength Beam fade time duration. + * @param amplitude Beam amplitude. + * @param color Color array (r, g, b, a). + * @param speed Speed of the beam. + * @noreturn + */ +stock Effect_DrawAxisOfRotationToClient( + client, + const Float:origin[3], + const Float:length[3], + const Float:angles[3], + modelIndex, + haloIndex, + startFrame=0, + frameRate=30, + Float:life=5.0, + Float:width=5.0, + Float:endWidth=5.0, + fadeLength=2, + Float:amplitude=1.0, + speed=0 +) { + new clients[1]; + clients[0] = client; + Effect_DrawAxisOfRotation(clients, 1, origin, length, angles, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, speed); +} + +/** + * Displays the given axis of rotation as beam effect to all players. + * + * @param origin Origin/center of the box. + * @param angles Angles used to rotate the box. + * @param length The length in each direction. + * @param modelIndex Precached model index. + * @param haloIndex Precached model index. + * @param startFrame Initital frame to render. + * @param frameRate Beam frame rate. + * @param life Time duration of the beam. + * @param width Initial beam width. + * @param endWidth Final beam width. + * @param fadeLength Beam fade time duration. + * @param amplitude Beam amplitude. + * @param color Color array (r, g, b, a). + * @param speed Speed of the beam. + * @noreturn + */ +stock Effect_DrawAxisOfRotationToAll( + const Float:origin[3], + const Float:length[3], + const Float:angles[3], + modelIndex, + haloIndex, + startFrame=0, + frameRate=30, + Float:life=5.0, + Float:width=5.0, + Float:endWidth=5.0, + fadeLength=2, + Float:amplitude=1.0, + speed=0 +) +{ + new clients[MaxClients]; + new numClients = Client_Get(clients, CLIENTFILTER_INGAME); + + Effect_DrawAxisOfRotation(clients, numClients, origin, length, angles, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, speed); +} + +/** + * Displays the given axis of rotation as beam effect to a list of players. + * + * @param clients An array of clients to show the box to. + * @param numClients Number of players in the array. + * @param origin Origin/center of the box. + * @param angles Angles used to rotate the box. + * @param length The length in each direction. + * @param modelIndex Precached model index. + * @param haloIndex Precached model index. + * @param startFrame Initital frame to render. + * @param frameRate Beam frame rate. + * @param life Time duration of the beam. + * @param width Initial beam width. + * @param endWidth Final beam width. + * @param fadeLength Beam fade time duration. + * @param amplitude Beam amplitude. + * @param color Color array (r, g, b, a). + * @param speed Speed of the beam. + * @noreturn + */ +stock Effect_DrawAxisOfRotation( + clients[], + numClients, + const Float:origin[3], + const Float:angles[3], + const Float:length[3], + modelIndex, + haloIndex, + startFrame=0, + frameRate=30, + Float:life=5.0, + Float:width=5.0, + Float:endWidth=5.0, + fadeLength=2, + Float:amplitude=1.0, + speed=0 +) { + // Create the additional corners of the box + new Float:xAxis[3], Float:yAxis[3], Float:zAxis[3]; + xAxis[0] = length[0]; + yAxis[1] = length[1]; + zAxis[2] = length[2]; + + // Rotate all edges + Math_RotateVector(xAxis, angles, xAxis); + Math_RotateVector(yAxis, angles, yAxis); + Math_RotateVector(zAxis, angles, zAxis); + + // Apply world offset (after rotation) + AddVectors(origin, xAxis, xAxis); + AddVectors(origin, yAxis, yAxis); + AddVectors(origin, zAxis, zAxis); + + // Draw all + TE_SetupBeamPoints(origin, xAxis, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, {255, 0, 0, 255}, speed); + TE_Send(clients, numClients); + + TE_SetupBeamPoints(origin, yAxis, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, {0, 255, 0, 255}, speed); + TE_Send(clients, numClients); + + TE_SetupBeamPoints(origin, zAxis, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, {0, 0, 255, 255}, speed); + TE_Send(clients, numClients); +} + + +/** + * Creates an env_sprite. + * + * @param origin Origin of the Sprite. + * @param modelIndex Precached model index. + * @param color Color array (r, g, b, a). + * @param scale Scale (Note: many materials ignore a lower value than 0.25). + * @param targetName Targetname of the sprite. + * @param parent Entity Index of this sprite's parent in the movement hierarchy. + * @param renderMode Render mode (use the enum). + * @param renderFx Render fx (use the enum). + * @param glowProxySize Radius size of the glow when to be rendered, if inside a geometry. Ex: a block 2x2x2 units big, if the glowProxySize is between 0.0 and 2.0 the sprite will not be rendered, even if the actual size of the sprite is bigger, everything above 2.0 will render the sprite. Using an abnormal high value will render Sprites trough walls. + * @param frameRate Sprite frame rate. + * @param hdrColorScale Float value to multiply sprite color by when running with HDR. + * @param receiveShadows When false then this prevents the sprite from receiving shadows. + * @return Entity Index of the created Sprite. + */ +stock Effect_EnvSprite( + const Float:origin[3], + modelIndex, + const color[4]={255, 255, 255, 255}, + Float:scale=0.25, + const String:targetName[MAX_NAME_LENGTH]="", + parent=-1, + RenderMode:renderMode=RENDER_WORLDGLOW, + RenderFx:renderFx=RENDERFX_NONE, + Float:glowProxySize=2.0, + Float:framerate=10.0, + Float:hdrColorScale=1.0, + bool:receiveShadows = true +) { + new entity = Entity_Create("env_sprite"); + + if (entity == INVALID_ENT_REFERENCE) { + return INVALID_ENT_REFERENCE; + } + + DispatchKeyValue (entity, "disablereceiveshadows", (receiveShadows) ? "0" : "1"); + DispatchKeyValueFloat (entity, "framerate", framerate); + DispatchKeyValueFloat (entity, "GlowProxySize", glowProxySize); + DispatchKeyValue (entity, "spawnflags", "1"); + DispatchKeyValueFloat (entity, "HDRColorScale", hdrColorScale); + DispatchKeyValue (entity, "maxdxlevel", "0"); + DispatchKeyValue (entity, "mindxlevel", "0"); + DispatchKeyValueFloat (entity, "scale", scale); + + DispatchSpawn(entity); + + SetEntityRenderMode(entity, renderMode); + SetEntityRenderColor(entity, color[0], color[1], color[2], color[3]); + SetEntityRenderFx(entity, renderFx); + + Entity_SetName(entity, targetName); + Entity_SetModelIndex(entity, modelIndex); + Entity_SetAbsOrigin(entity, origin); + + if (parent != -1) { + Entity_SetParent(entity, parent); + } + + return entity; +} + diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/entities.inc b/gameserver/addons/sourcemod/scripting/include/smlib/entities.inc index 89708b9..e5280ce 100644 --- a/gameserver/addons/sourcemod/scripting/include/smlib/entities.inc +++ b/gameserver/addons/sourcemod/scripting/include/smlib/entities.inc @@ -7,6 +7,14 @@ #include #include +/** + * Macro for iterating trough all children (entities it is parent of) of an entity. + * + * @param 1 Entity Index of the parent. + * @param 2 Name of the children entity index variable (will be only valid in the loop). + */ +#define LOOP_CHILDREN(%1,%2) for (new %2=Entity_GetNextChild(%1); %2 != INVALID_ENT_REFERENCE; %2=Entity_GetNextChild(%1, ++%2)) + /* * Checks if an entity is valid and exists. * @@ -27,12 +35,12 @@ stock Entity_IsValid(entity) * cheaper, use this if you call this function very often. * * @param name Name of the entity you want so search. - * @param class Optional: Classname of the entity + * @param className Optional: Classname of the entity * @return Entity index or INVALID_ENT_REFERENCE if not matching entity was found. */ -stock Entity_FindByName(const const String:name[], const String:class[]="") +stock Entity_FindByName(const const String:name[], const String:className[]="") { - if (class[0] == '\0') { + if (className[0] == '\0') { // Hack: Double the limit to gets none-networked entities too. new realMaxEntities = GetMaxEntities() * 2; for (new entity=0; entity < realMaxEntities; entity++) { @@ -48,7 +56,7 @@ stock Entity_FindByName(const const String:name[], const String:class[]="") } else { new entity = INVALID_ENT_REFERENCE; - while ((entity = FindEntityByClassname(entity, class)) != INVALID_ENT_REFERENCE) { + while ((entity = FindEntityByClassname(entity, className)) != INVALID_ENT_REFERENCE) { if (Entity_NameMatches(entity, name)) { return entity; @@ -70,12 +78,12 @@ stock Entity_FindByName(const const String:name[], const String:class[]="") * cheaper, use this if you call this function very often. * * @param hammerId Hammer editor ID - * @param class Optional: Classname of the entity + * @param className Optional: Classname of the entity * @return Edict Index or INVALID_ENT_REFERENCE if no entity was found. */ -stock Entity_FindByHammerId(hammerId, const String:class[]="") +stock Entity_FindByHammerId(hammerId, const String:className[]="") { - if (class[0] == '\0') { + if (className[0] == '\0') { // Hack: Double the limit to gets none-networked entities too. new realMaxEntities = GetMaxEntities() * 2; for (new entity=0; entity < realMaxEntities; entity++) { @@ -91,7 +99,7 @@ stock Entity_FindByHammerId(hammerId, const String:class[]="") } else { new entity = INVALID_ENT_REFERENCE; - while ((entity = FindEntityByClassname(entity, class)) != INVALID_ENT_REFERENCE) { + while ((entity = FindEntityByClassname(entity, className)) != INVALID_ENT_REFERENCE) { if (Entity_GetHammerId(entity) == hammerId) { return entity; @@ -118,10 +126,11 @@ stock Entity_FindByClassName(startEntity, const String:className[]) } /** - * Checks if an entity matches a specific entity class. + * Checks if an entity (partially) matches a specific entity class. * * @param entity Entity Index. - * @param class Classname String. + * @param className Classname String. + * @partialMatch If to do a partial classname check. * @return True if the classname matches, false otherwise. */ stock bool:Entity_ClassNameMatches(entity, const String:className[], partialMatch=false) @@ -132,7 +141,7 @@ stock bool:Entity_ClassNameMatches(entity, const String:className[], partialMatc if (partialMatch) { return (StrContains(entity_className, className) != -1); } - + return StrEqual(entity_className, className); } @@ -157,11 +166,11 @@ stock bool:Entity_NameMatches(entity, const String:name[]) * @param entity Entity index. * @param buffer Return/Output buffer. * @param size Max size of buffer. - * @noreturn + * @return Number of non-null bytes written. */ stock Entity_GetName(entity, String:buffer[], size) { - GetEntPropString(entity, Prop_Data, "m_iName", buffer, size); + return GetEntPropString(entity, Prop_Data, "m_iName", buffer, size); } /** @@ -169,14 +178,14 @@ stock Entity_GetName(entity, String:buffer[], size) * * @param entity Entity index. * @param name The name you want to give. - * @noreturn + * @return True on success, false otherwise. */ stock Entity_SetName(entity, const String:name[], any:...) { decl String:format[128]; VFormat(format, sizeof(format), name, 3); - DispatchKeyValue(entity, "targetname", format); + return DispatchKeyValue(entity, "targetname", format); } /** @@ -187,17 +196,11 @@ stock Entity_SetName(entity, const String:name[], any:...) * @param entity Entity index. * @param buffer Return/Output buffer. * @param size Max size of buffer. - * @return + * @return Number of non-null bytes written. */ stock Entity_GetClassName(entity, String:buffer[], size) { - GetEntPropString(entity, Prop_Data, "m_iClassname", buffer, size); - - if (buffer[0] == '\0') { - return false; - } - - return true; + return GetEntPropString(entity, Prop_Data, "m_iClassname", buffer, size); } /** @@ -205,11 +208,11 @@ stock Entity_GetClassName(entity, String:buffer[], size) * * @param entity Entity index. * @param name The name you want to give. - * @noreturn + * @return True on success, false otherwise. */ stock Entity_SetClassName(entity, const String:className[]) { - DispatchKeyValue(entity, "classname", className); + return DispatchKeyValue(entity, "classname", className); } /** @@ -218,11 +221,11 @@ stock Entity_SetClassName(entity, const String:className[]) * @param entity Entity index. * @param buffer Return/Output buffer. * @param size Max size of buffer. - * @noreturn + * @return Number of non-null bytes written. */ stock Entity_GetTargetName(entity, String:buffer[], size) { - GetEntPropString(entity, Prop_Data, "m_target", buffer, size); + return GetEntPropString(entity, Prop_Data, "m_target", buffer, size); } /** @@ -230,14 +233,14 @@ stock Entity_GetTargetName(entity, String:buffer[], size) * * @param entity Entity index. * @param name The target name you want to set - * @noreturn + * @return True on success, false otherwise. */ stock Entity_SetTargetName(entity, const String:name[], any:...) { decl String:format[128]; VFormat(format, sizeof(format), name, 3); - DispatchKeyValue(entity, "target", format); + return DispatchKeyValue(entity, "target", format); } /** @@ -246,11 +249,11 @@ stock Entity_SetTargetName(entity, const String:name[], any:...) * @param entity Entity index. * @param buffer Return/Output buffer. * @param size Max size of buffer. - * @noreturn + * @return Number of non-null bytes written. */ stock Entity_GetGlobalName(entity, String:buffer[], size) { - GetEntPropString(entity, Prop_Data, "m_iGlobalname", buffer, size); + return GetEntPropString(entity, Prop_Data, "m_iGlobalname", buffer, size); } /** @@ -258,14 +261,14 @@ stock Entity_GetGlobalName(entity, String:buffer[], size) * * @param entity Entity index. * @param name The global name you want to set. - * @noreturn + * @return True on success, false otherwise. */ stock Entity_SetGlobalName(entity, const String:name[], any:...) { decl String:format[128]; VFormat(format, sizeof(format), name, 3); - DispatchKeyValue(entity, "globalname", format); + return DispatchKeyValue(entity, "globalname", format); } /** @@ -274,11 +277,11 @@ stock Entity_SetGlobalName(entity, const String:name[], any:...) * @param entity Entity index. * @param buffer Return/Output buffer. * @param size Max size of buffer. - * @noreturn + * @return Number of non-null bytes written. */ stock Entity_GetParentName(entity, String:buffer[], size) { - GetEntPropString(entity, Prop_Data, "m_iParent", buffer, size); + return GetEntPropString(entity, Prop_Data, "m_iParent", buffer, size); } /** @@ -286,14 +289,14 @@ stock Entity_GetParentName(entity, String:buffer[], size) * * @param entity Entity index. * @param name The parent name you want to set. - * @noreturn + * @return True on success, false otherwise. */ stock Entity_SetParentName(entity, const String:name[], any:...) { decl String:format[128]; VFormat(format, sizeof(format), name, 3); - DispatchKeyValue(entity, "parentname", format); + return DispatchKeyValue(entity, "parentname", format); } /** @@ -351,7 +354,7 @@ stock Entity_GetMinSize(entity, Float:vec[3]) * @param vec Vector. * @noreturn */ -stock Entity_SetMinSize(entity, Float:vecMins[3]) +stock Entity_SetMinSize(entity, const Float:vecMins[3]) { SetEntPropVector(entity, Prop_Send, "m_vecMins", vecMins); } @@ -377,7 +380,7 @@ stock Entity_GetMaxSize(entity, Float:vec[3]) * @param vec Vector. * @noreturn */ -stock Entity_SetMaxSize(entity, Float:vecMaxs[3]) +stock Entity_SetMaxSize(entity, const Float:vecMaxs[3]) { SetEntPropVector(entity, Prop_Send, "m_vecMaxs", vecMaxs); } @@ -828,6 +831,8 @@ stock Entity_SetSolidFlags(entity, SolidFlags_t:flags) if (oldFlags == flags) { return; } + + SetEntProp(entity, Prop_Data, "m_usSolidFlags", flags, 2); // These two flags, if changed, can produce different surrounding bounds if ((oldFlags & (FSOLID_FORCE_WORLD_ALIGNED | FSOLID_USE_TRIGGER_BOUNDS)) != @@ -920,7 +925,7 @@ stock SolidType_t:Entity_GetSolidType(entity) */ stock Entity_SetSolidType(entity, SolidType_t:value) { - SetEntProp(entity, Prop_Data, "m_nSolidType", value, 1); + SetEntProp(entity, Prop_Send, "m_nSolidType", value, 1); Entity_MarkSurrBoundsDirty(entity); } @@ -943,11 +948,11 @@ stock bool:Entity_IsSolid(entity) * @param entity entity reference or index * @param model buffer String for the model * @param size max size of buffer string - * @noreturn + * @return Number of non-null bytes written. */ stock Entity_GetModel(entity, String:buffer[], size) { - GetEntPropString(entity, Prop_Data, "m_ModelName", buffer, size); + return GetEntPropString(entity, Prop_Data, "m_ModelName", buffer, size); } /** @@ -1067,7 +1072,7 @@ stock Entity_SetCollisionGroup(entity, Collision_Group_t:value) */ stock Entity_GetAbsOrigin(entity, Float:vec[3]) { - GetEntPropVector(entity, Prop_Data, "m_vecOrigin", vec); + GetEntPropVector(entity, Prop_Send, "m_vecOrigin", vec); } /** @@ -1077,7 +1082,7 @@ stock Entity_GetAbsOrigin(entity, Float:vec[3]) * @param vec 3 dimensional vector array. * @noreturn */ -stock Entity_SetAbsOrigin(entity, Float:vec[3]) +stock Entity_SetAbsOrigin(entity, const Float:vec[3]) { // We use TeleportEntity to set the origin more safely // Todo: Replace this with a call to UTIL_SetOrigin() or CBaseEntity::SetLocalOrigin() @@ -1109,7 +1114,7 @@ stock Entity_GetAbsAngles(entity, Float:vec[3]) * @param vec 3 dimensional vector array. * @noreturn */ -stock Entity_SetAbsAngles(entity, Float:vec[3]) +stock Entity_SetAbsAngles(entity, const Float:vec[3]) { // We use TeleportEntity to set the angles more safely // Todo: Replace this with a call to CBaseEntity::SetLocalAngles() @@ -1295,8 +1300,8 @@ stock Entity_AddHealth(entity, value, ignoreMax=false, kill=true) new health = Entity_GetHealth(entity); health += value; - - return Entity_SetHealth(entity, value, ignoreMax, kill); + + return Entity_SetHealth(entity, health, ignoreMax, kill); } /** @@ -1312,7 +1317,7 @@ stock Entity_TakeHealth(entity, value, ignoreMax=false, kill=true) health -= value; - return Entity_SetHealth(entity, value, ignoreMax, kill); + return Entity_SetHealth(entity, health, ignoreMax, kill); } /** @@ -1543,9 +1548,10 @@ stock Entity_Create(const String:className[], ForceEdictIndex=-1) * If the entity is is player ForcePlayerSuicide() is called. * * @param kenny Entity index. - * @return True on success, false otherwise + * @param killChildren When true, kennys children are killed too. + * @return True on success, false otherwise. */ -stock bool:Entity_Kill(kenny) +stock bool:Entity_Kill(kenny, killChildren=false) { if (Entity_IsPlayer(kenny)) { // Oh My God! They Killed Kenny!! @@ -1553,7 +1559,12 @@ stock bool:Entity_Kill(kenny) return true; } - return AcceptEntityInput(kenny, "kill"); + if(killChildren){ + return AcceptEntityInput(kenny, "KillHierarchy"); + } + else { + return AcceptEntityInput(kenny, "Kill"); + } } /** @@ -1729,7 +1740,7 @@ stock Entity_GetParent(entity) * @param entity Entity Index. * @noreturn */ -stock Entity_RemoveParent(entity) +stock Entity_ClearParent(entity) { SetVariantString(""); AcceptEntityInput(entity, "ClearParent"); @@ -1742,10 +1753,388 @@ stock Entity_RemoveParent(entity) * @param parentEntity Entity Index of the new parent. * @noreturn */ -stock Entity_SetParent(entity, parentEntity) +stock Entity_SetParent(entity, parent) { SetVariantString("!activator"); - AcceptEntityInput(entity, "SetParent", parentEntity); + AcceptEntityInput(entity, "SetParent", parent); +} + + +/* + * Callback for Change_OverTime. + * Note that every parameter is a reference and can be changed during this callback. + * You can get the elapsed time since start by multiply tick with currentCall. + * + * @param entity Entity Index. + * @param interval The current interval from the current game time to execute the next call of this function. + * @param currentCall The current call number (0 is the 1st call at 0.0 seconds, 1 the 2nd call at tick*1 seconds, ...). + * @return When true this callback will be called again at the next defined tick, otherwise it won't. + */ +functag Entity_ChangeOverTimeCallback bool:public(&entity, &Float:interval, ¤tCall); + +/* + * Creates a timer and provides a callback to change various things about an entity over time. + * + * @param entity Entity Index. + * @param interval Interval from the current game time to execute the given function. + * @noreturn + */ +stock Entity_ChangeOverTime(entity, Float:interval=0.1, Entity_ChangeOverTimeCallback:valueCallback) +{ + new Handle:dataPack = CreateDataPack(); + WritePackCell(dataPack, EntIndexToEntRef(entity)); + WritePackFloat(dataPack, interval); + WritePackCell(dataPack, 0); + WritePackCell(dataPack, _:valueCallback); + ResetPack(dataPack); + __smlib_Timer_ChangeOverTime(INVALID_HANDLE,dataPack); +} + +public Action:__smlib_Timer_ChangeOverTime(Handle:Timer, Handle:dataPack) +{ + new entity = EntRefToEntIndex(ReadPackCell(dataPack)); + if(!Entity_IsValid(entity)){ + return Plugin_Stop; + } + + new Float:interval = ReadPackFloat(dataPack); + new currentCall = ReadPackCell(dataPack); + new Entity_ChangeOverTimeCallback:callback = Entity_ChangeOverTimeCallback:ReadPackCell(dataPack); + new any:result; + Call_StartFunction(INVALID_HANDLE, callback); + Call_PushCellRef(entity); + Call_PushFloatRef(interval); + Call_PushCellRef(currentCall); + Call_Finish(result); + + if(result == false){ + return Plugin_Stop; + } + + ResetPack(dataPack,true); + WritePackCell(dataPack, EntIndexToEntRef(entity)); + WritePackFloat(dataPack, interval); + WritePackCell(dataPack, currentCall+1); + WritePackCell(dataPack, _:callback); + ResetPack(dataPack); + CreateTimer(interval,__smlib_Timer_ChangeOverTime,dataPack); + return Plugin_Stop; +} + + +/** + * Gets the next child, entity is parent of. + * + * @param client Entity Index (of Parent) + * @param start Start Index. + * @return Entity Index or -1 if no entity was found. + */ +stock Entity_GetNextChild(parent, start=0) +{ + for (new entity=start; entity <= 2048; entity++) { + + if (!Entity_IsValid(entity)) { + continue; + } + + if (entity > 0 && entity <= MaxClients && !IsClientConnected(entity)) { + continue; + } + + if (Entity_GetParent(entity) == parent) { + return entity; + } + } + + return INVALID_ENT_REFERENCE; +} +/** + * Gets the move/open direction of an entity (only available for func_door*, prop_door* and func_movelinear). + * Ex: if vec[2] is 1.0 a func_door moves straight up. + * + * @param entity Entity index. + * @param vec Vector. + * @noreturn + */ +stock Entity_GetMoveDirection(entity, Float:vec[3]) +{ + GetEntPropVector(entity, Prop_Data, "m_vecMoveDir", vec); +} +/** + * Sets the move/open direction of an entity (only available for func_door*, prop_door* and func_movelinear). + * Ex: if vec[2] is 1.0 a func_door moves straight up. + * + * @param entity Entity index. + * @param vec Vector. + * @noreturn + */ +stock Entity_SetMoveDirection(entity, const Float:vec[3]) +{ + SetEntPropVector(entity, Prop_Data, "m_vecMoveDir", vec); } +/** + * Returns if the entity will force close (won't be blockable by players and/or objects) or not when triggered to move. + * + * @param entity Entity index. + * @return True if the door will force close, otherwise false. + */ +stock bool:Entity_GetForceClose(entity) +{ + return bool:GetEntProp(entity, Prop_Data, "m_bForceClosed"); +} + +/** + * Sets if the door should force close (souldn't be blockable by players and/or objects) or not when triggered to move. + * + * @param entity Entity index. + * @param forceClose If true the door will force close, otherwise it won't. + * @noreturn + */ +stock Entity_SetForceClose(entity, bool:forceClose) +{ + SetEntProp(entity, Prop_Data, "m_bForceClosed", forceClose); +} + +/** + * Gets the speed of a moving entity (like doors: open close speed). + * + * @param entity Entity index. + * @return Speed of the entity. + */ +stock Float:Entity_GetSpeed(entity) +{ + return GetEntPropFloat(entity, Prop_Data, "m_flSpeed"); +} + +/** + * Sets how fast an entity moves (like doors: open close speed). + * + * @param entity Entity index. + * @param speed The new speed of the entity. + * @noreturn + */ +stock Entity_SetSpeed(entity, Float:speed) +{ + SetEntPropFloat(entity, Prop_Data, "m_flSpeed", speed); +} + +/** + * Gets the damage of a moving entity when blocked (like doors when open or close and players and/or objects are between the entity and something else). + * Note: Negative values add health to the blocking entity. + * + * @param entity Entity index. + * @return Damage. + */ +stock Float:Entity_GetBlockDamage(entity) +{ + return GetEntPropFloat(entity, Prop_Data, "m_flBlockDamage"); +} + +/** + * Sets the damage of a moving entity when blocked (like doors when open or close and players and/or objects are between the entity and something else). + * Note: Negative values add health to the blocking entity. + * + * @param entity Entity index. + * @param damage Damage. + * @noreturn + */ +stock Entity_SetBlockDamage(entity, Float:damage) +{ + SetEntPropFloat(entity, Prop_Data, "m_flBlockDamage", damage); +} + +/** + * Returns if the given entity is disabled or not. + * + * @param entity Entity index. + * @return True if entity is disabled, otherwise false. + */ +stock bool:Entity_IsDisabled(entity) +{ + return bool:GetEntProp(entity, Prop_Data, "m_bDisabled", 1); +} + +/** + * Disables the given entity. + * + * @param entity Entity index. + * @return True if successful otherwise false. + */ +stock Entity_Disable(entity) +{ + return AcceptEntityInput(entity, "Disable"); +} + +/** + * Enables the given entity. + * + * @param entity Entity index. + * @return True if successful otherwise false. + */ +stock Entity_Enable(entity) +{ + return AcceptEntityInput(entity, "Enable"); +} + + +// settings for m_takedamage taken from hl2sdk-ob-valve\game\shared\shareddefs.h +#define DAMAGE_NO 0 +#define DAMAGE_EVENTS_ONLY 1 // Call damage functions, but don't modify health +#define DAMAGE_YES 2 +#define DAMAGE_AIM 3 + +/** + * Sets the mode for an entity to take damage. + * Note: This is used to give a client god mode (DAMAGE_NO). + * + * @param entity Entity index. + * @param value Mode, use DAMAGE_* defines. + * @noreturn + */ +stock Entity_SetTakeDamage(entity, value) +{ + SetEntProp(entity, Prop_Data, "m_takedamage", value, 1); +} + +/** + * Gets the mode for an entity to take damage. + * Note: When the return value is DAMAGE_NO then the client is using godmode. + * + * @param entity Entity index. + * @return Take damage mode (DAMAGE_*). + */ +stock Entity_GetTakeDamage(entity) +{ + return GetEntProp(entity, Prop_Data, "m_takedamage", 1); +} + +/** + * Sets the minimum of damage required to hurt this entity. + * Example: This is used to block any damage done by projectile weapons against a gun ship in Half-Life 2. + * + * @param entity Entity index. + * @param minDamage Minimum required damage. + * @noreturn + */ +stock Entity_SetMinHealthDamage(entity, minDamage) +{ + SetEntProp(entity, Prop_Data, "m_iMinHealthDmg", minDamage); +} + +/** + * Gets the minimum of damage required to hurt this entity. + * Example: This is used to block any damage done by projectile weapons against a gun ship in Half-Life 2. + * + * @param entity Entity index. + * @return Minimum required damage. + */ +stock Entity_GetMinHealthDamage(entity) +{ + return GetEntProp(entity, Prop_Data, "m_iMinHealthDmg"); +} + +/** + * Gets an entity's color. + * + * @param entity Entity index + * @param color 4 dimensional array where [r,g,b,a] values are stored + * @noreturn + * @error Invalid entity index, or lack of mod compliance. + */ +stock Entity_GetRenderColor(entity, color[4]) +{ + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_clrRender", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) { + strcopy(prop, sizeof(prop), "m_clrRender"); + } + + gotconfig = true; + } + + new offset = GetEntSendPropOffs(entity, prop); + + if (offset <= 0) { + ThrowError("SetEntityRenderColor not supported by this mod"); + } + + for (new i=0; i < 4; i++) { + color[i] = GetEntData(entity, offset + i + 1, 1); + } +} + +/** + * Sets an entity's color. + * Doesn't change the value, if set to -1. + * + * @param entity Entity index + * @param r Amount of red (0-255) + * @param g Amount of green (0-255) + * @param b Amount of blue (0-255) + * @param a Amount of alpha (0-255) + * @noreturn + * @error Invalid entity index, or lack of mod compliance. + */ +stock Entity_SetRenderColor(entity, r=-1, g=-1, b=-1, a=-1) +{ + static bool:gotconfig = false; + static String:prop[32]; + + if (!gotconfig) { + new Handle:gc = LoadGameConfigFile("core.games"); + new bool:exists = GameConfGetKeyValue(gc, "m_clrRender", prop, sizeof(prop)); + CloseHandle(gc); + + if (!exists) { + strcopy(prop, sizeof(prop), "m_clrRender"); + } + + gotconfig = true; + } + + new offset = GetEntSendPropOffs(entity, prop); + + if (offset <= 0) { + ThrowError("SetEntityRenderColor not supported by this mod"); + } + + if(r != -1) { + SetEntData(entity, offset, r, 1, true); + } + + if(g != -1) { + SetEntData(entity, offset + 1, g, 1, true); + } + + if(b != -1) { + SetEntData(entity, offset + 2, b, 1, true); + } + + if(a != -1) { + SetEntData(entity, offset + 3, a, 1, true); + } +} + +/** + * Sends the 'addouput' command to an entity. + * + * @param entity Entity Index. + * @param input Input command. + * @param activator Entity index which initiated the sequence of actions (-1 for a NULL entity). + * @param caller Entity index from which this event is sent (-1 for a NULL entity). + * @param outputid Unknown. + * @return True if successful, otherwise false. + */ +stock bool:Entity_AddOutput(entity, const String:input[], activator=-1, caller=-1, outputid=0) +{ + SetVariantString(input); + return AcceptEntityInput(entity, "addoutput", activator, caller, outputid); +} diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/files.inc b/gameserver/addons/sourcemod/scripting/include/smlib/files.inc index dc7ffed..3fda876 100644 --- a/gameserver/addons/sourcemod/scripting/include/smlib/files.inc +++ b/gameserver/addons/sourcemod/scripting/include/smlib/files.inc @@ -4,7 +4,7 @@ #define _smlib_files_included #include -#include +#include #include /** @@ -145,7 +145,7 @@ stock File_AddToDownloadsTable(const String:path[], bool:recursive=true, const S if (FileExists(path)) { - new String:fileExtension[4]; + new String:fileExtension[5]; File_GetExtension(path, fileExtension, sizeof(fileExtension)); if (StrEqual(fileExtension, "bz2", false) || StrEqual(fileExtension, "ztmp", false)) { @@ -265,36 +265,42 @@ stock File_ReadDownloadList(const String:path[]) } /* - * Attempts to load a translation file and unloads the plugin if the file doesn't exist. + * Attempts to load a translation file and optionally unloads the plugin if the file + * doesn't exist (also prints an error message). * - * @param file Filename of the translations file (eg. .phrases). - * @noreturn + * @param file Filename of the translations file (eg. .phrases). + * @param setFailState If true, it sets the failstate if the translations file doesn't exist + * @return True on success, false otherwise (only if setFailState is set to false) */ -stock File_LoadTranslations(const String:file[]) +stock File_LoadTranslations(const String:file[], setFailState=true) { decl String:path[PLATFORM_MAX_PATH]; - - Format(path,sizeof(path),"translations/%s",file); - - BuildPath(Path_SM, path, sizeof(path), path); - + + BuildPath(Path_SM, path, sizeof(path), "translations/%s", file); + if (FileExists(path)) { LoadTranslations(file); - return; + return true; } - - Format(path,sizeof(path),"%s.txt",path); - - if (FileExists(path)) { - LoadTranslations(file); - return; + + Format(path,sizeof(path), "%s.txt", path); + + if (!FileExists(path)) { + + if (setFailState) { + SetFailState("Unable to locate translation file (%s).", path); + } + + return false; } - - SetFailState("Unable to locate translation file (%s).",path); + + LoadTranslations(file); + + return true; } /* - * Reads the contents of a given file into a string buffer in binaey mode. + * Reads the contents of a given file into a string buffer in binary mode. * * @param path Path to the file * @param buffer String buffer diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/general.inc b/gameserver/addons/sourcemod/scripting/include/smlib/general.inc index 1a0b402..a7d004c 100644 --- a/gameserver/addons/sourcemod/scripting/include/smlib/general.inc +++ b/gameserver/addons/sourcemod/scripting/include/smlib/general.inc @@ -235,3 +235,17 @@ stock bool:IsIPLocal(ip) return false; } + +/* + * Closes the given hindle and sets it to INVALID_HANDLE. + * + * @param handle handle + * @noreturn + */ +stock ClearHandle(&Handle:handle) +{ + if (handle != INVALID_HANDLE) { + CloseHandle(handle); + handle = INVALID_HANDLE; + } +} diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/math.inc b/gameserver/addons/sourcemod/scripting/include/smlib/math.inc index beec68e..16019a8 100644 --- a/gameserver/addons/sourcemod/scripting/include/smlib/math.inc +++ b/gameserver/addons/sourcemod/scripting/include/smlib/math.inc @@ -21,22 +21,20 @@ enum VecAngle /** * Makes a negative integer number to a positive integer number. + * This is faster than Sourcemod's native FloatAbs() for integers. + * Use FloatAbs() for Float numbers. * * @param number A number that can be positive or negative. * @return Positive number. */ -stock any:Math_Abs(any:number) +stock Math_Abs(value) { - if (number >= 0) { - return number; - } - - return (number * -1); + return (value ^ (value >> 31)) - (value >> 31); } /** * Checks if 2 vectors are equal. - * You can specfiy a tolerance. + * You can specfiy a tolerance, which is the maximum distance at which vectors are considered equals * * @param vec1 First vector (3 dim array) * @param vec2 Second vector (3 dim array) @@ -45,9 +43,9 @@ stock any:Math_Abs(any:number) */ stock bool:Math_VectorsEqual(Float:vec1[3], Float:vec2[3], Float:tolerance=0.0) { - new Float:distance = GetVectorDistance(vec1, vec2); + new Float:distance = GetVectorDistance(vec1, vec2, true); - return distance <= tolerance; + return distance <= (tolerance * tolerance); } /** @@ -215,6 +213,79 @@ stock Math_MoveVector(const Float:start[3], const Float:end[3], Float:scale, Flo AddVectors(start,output,output); } +/** + * Puts x, y and z into a vector. + * + * @param x Float value. + * @param y Float value. + * @param z Float value. + * @param result Output vector. + * @noreturn + */ +stock Math_MakeVector(const Float:x, const Float:y, const Float:z, Float:result[3]) +{ + result[0] = x; + result[1] = y; + result[2] = z; +} + +/** + * Rotates a vector around its zero-point. + * Note: As example you can rotate mins and maxs of an entity and then add its origin to mins and maxs to get its bounding box in relation to the world and its rotation. + * When used with players use the following angle input: + * angles[0] = 0.0; + * angles[1] = 0.0; + * angles[2] = playerEyeAngles[1]; + * + * @param vec Vector to rotate. + * @param angles How to rotate the vector. + * @param result Output vector. + * @noreturn + */ +stock Math_RotateVector(const Float:vec[3], const Float:angles[3], Float:result[3]) +{ + // First the angle/radiant calculations + decl Float:rad[3]; + // I don't really know why, but the alpha, beta, gamma order of the angles are messed up... + // 2 = xAxis + // 0 = yAxis + // 1 = zAxis + rad[0] = DegToRad(angles[2]); + rad[1] = DegToRad(angles[0]); + rad[2] = DegToRad(angles[1]); + + // Pre-calc function calls + new Float:cosAlpha = Cosine(rad[0]); + new Float:sinAlpha = Sine(rad[0]); + new Float:cosBeta = Cosine(rad[1]); + new Float:sinBeta = Sine(rad[1]); + new Float:cosGamma = Cosine(rad[2]); + new Float:sinGamma = Sine(rad[2]); + + // 3D rotation matrix for more information: http://en.wikipedia.org/wiki/Rotation_matrix#In_three_dimensions + new Float:x = vec[0], Float:y = vec[1], Float:z = vec[2]; + new Float:newX, Float:newY, Float:newZ; + newY = cosAlpha*y - sinAlpha*z; + newZ = cosAlpha*z + sinAlpha*y; + y = newY; + z = newZ; + + newX = cosBeta*x + sinBeta*z; + newZ = cosBeta*z - sinBeta*x; + x = newX; + z = newZ; + + newX = cosGamma*x - sinGamma*y; + newY = cosGamma*y + sinGamma*x; + x = newX; + y = newY; + + // Store everything... + result[0] = x; + result[1] = y; + result[2] = z; +} + /** * Converts Source Game Units to metric Meters * diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/menus.inc b/gameserver/addons/sourcemod/scripting/include/smlib/menus.inc new file mode 100644 index 0000000..c0c825d --- /dev/null +++ b/gameserver/addons/sourcemod/scripting/include/smlib/menus.inc @@ -0,0 +1,38 @@ +#if defined _smlib_menus_included + #endinput +#endif +#define _smlib_menus_included + +#include +#include + +/** + * Adds an option to a menu with a String display but an integer + * identifying the option. + * + * @param menu Handle to the menu + * @param value Integer value for the option + * @param display Display text for the menu + * @noreturn + */ +stock Menu_AddIntItem(Handle:menu, any:value, String:display[]) +{ + decl String:buffer[INT_MAX_DIGITS + 1]; + IntToString(value, buffer, sizeof(buffer)); + AddMenuItem(menu, buffer, display); +} + +/** + * Retrieves an integer-value choice from a menu, where the + * menu's information strings were created as integers. + * + * @param menu Handle to the menu + * @param param2 The item position selected from the menu. + * @return Integer choice from the menu, or 0 if the integer could not be parsed. + */ +stock any:Menu_GetIntItem(Handle:menu, any:param2) +{ + decl String:buffer[INT_MAX_DIGITS + 1]; + GetMenuItem(menu, param2, buffer, sizeof(buffer)); + return StringToInt(buffer); +} diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/pluginmanager.inc b/gameserver/addons/sourcemod/scripting/include/smlib/pluginmanager.inc index a3501be..a81c96a 100644 --- a/gameserver/addons/sourcemod/scripting/include/smlib/pluginmanager.inc +++ b/gameserver/addons/sourcemod/scripting/include/smlib/pluginmanager.inc @@ -1,366 +1,199 @@ -/***************************************************************** - - - SMLib's PluginManager (Alpha release) - - -*****************************************************************/ -#include - -/***************************************************************** - - - D O U B L E I N C L U D E P R E V E N T I O N - - -*****************************************************************/ #if defined _smlib_pluginmanager_included - #endinput + #endinput #endif #define _smlib_pluginmanager_included -/***************************************************************** - - - D E F I N E S - - -*****************************************************************/ -#define MAX_CONVAR_LENGTH 256 - -#define MAX_PLUGIN_NAME_LENGTH 128 -#define MAX_PLUGIN_SHORTNAME_LENGTH 128 -#define MAX_PLUGIN_TAG_LENGTH 16 -#define MAX_PLUGIN_FILENAME_LENGTH 128 +#include +#include -#define MAX_VERSION_INFO_LENGTH 512 +stock + Handle:Plugin_Handle = INVALID_HANDLE, + String:Plugin_Name[256], + String:Plugin_Author[256], + String:Plugin_Description[256], + String:Plugin_Version[256], + String:Plugin_VersionDescription[256], + Handle:Plugin_VersionCvar, + String:Plugin_EnableDescription[256], + String:Plugin_Url[256], + String:Plugin_Tag[256], + String:Plugin_Prefix[256], + String:Plugin_FileName[PLATFORM_MAX_PATH]; -/***************************************************************** - - G L O B A L V A R S - - -*****************************************************************/ -// ConVar Handles -new Handle:g_cvarVersion = INVALID_HANDLE; -new Handle:g_cvarEnable = INVALID_HANDLE; -new Handle:g_cvarDebug = INVALID_HANDLE; -new Handle:g_cvarDeveloper_Flag = INVALID_HANDLE; - -//ConVar Runtime optimizer -new g_iPlugin_Enable = 0; -new g_iPlugin_Debug = 0; -new AdminFlag:g_afPlugin_Developer_Flag = Admin_Root; - -//Plugin Info -new String:g_sPlugin_Name[MAX_PLUGIN_NAME_LENGTH]; -new String:g_sPlugin_Short_Name[MAX_PLUGIN_SHORTNAME_LENGTH]; -new String:g_sPlugin_Tag[MAX_PLUGIN_TAG_LENGTH]; -new String:g_sPlugin_File_Name[MAX_PLUGIN_FILENAME_LENGTH]; - -/***************************************************************** - - - F O R W A R D P U B L I C S - - -*****************************************************************/ /** - * SMLib Init function to take care of version, enable, debug and developerflag convars. - * - * @param name - * @param tag - * @param version - * @param author - * @param description - * @param url - * @noreturn - */ -stock SMLib_OnPluginStart(const String:name[],const String:tag[], const String:version[], const String:author[], const String:description[], const String:url[]){ - - //Name - strcopy(g_sPlugin_Name,sizeof(g_sPlugin_Name),name); - - //Shortname out of name - strcopy(g_sPlugin_Short_Name,sizeof(g_sPlugin_Short_Name),name); - ReplaceString(g_sPlugin_Short_Name,sizeof(g_sPlugin_Short_Name)," ","",false); - String_ToLower(g_sPlugin_Short_Name,g_sPlugin_Short_Name,sizeof(g_sPlugin_Short_Name)); - - //Tag - strcopy(g_sPlugin_Tag,sizeof(g_sPlugin_Tag),tag); - - //Filename - GetPluginFilename(INVALID_HANDLE,g_sPlugin_File_Name,sizeof(g_sPlugin_File_Name)); - - //Version - decl String:cvarVersionInfo[MAX_VERSION_INFO_LENGTH]; - Format(cvarVersionInfo,sizeof(cvarVersionInfo),"\n || %s ('%s') v%s\n || Builddate:'%s - %s'\n || Author(s):'%s'\n || URL:'%s'\n || Description:'%s'\n",g_sPlugin_Name,g_sPlugin_File_Name,version,__TIME__,__DATE__,author,url,description); - //needed if plugin has some late load: - g_cvarVersion = CreateConVarEx("version", version, cvarVersionInfo, FCVAR_PLUGIN|FCVAR_DONTRECORD|FCVAR_NOTIFY); - SetConVarString(g_cvarVersion,version); - - //Cvars - g_cvarEnable = CreateConVarEx("enable", "1", "Enables or Disables this plugin (1=Enable|0=Disable)",FCVAR_PLUGIN|FCVAR_NOTIFY,true,0.0); - g_cvarDebug = CreateConVarEx("debug", "0", "Enables or Disables debug mode of this plugin (3=ignore who is dev|2=SendToClient|1=Enable|0=Disabled)",FCVAR_PLUGIN|FCVAR_DONTRECORD,true,0.0,true,3.0); - g_cvarDeveloper_Flag = CreateConVarEx("developerflag", "z", "what admin flag is required to be an developer for this plugin",FCVAR_PLUGIN|FCVAR_DONTRECORD); - - //Cvar Runtime optimizer - g_iPlugin_Enable = GetConVarInt(g_cvarEnable); - g_iPlugin_Debug = GetConVarInt(g_cvarDebug); - decl String:tempFlag[2]; - GetConVarString(g_cvarDeveloper_Flag,tempFlag,sizeof(tempFlag)); - g_afPlugin_Developer_Flag = Admin_GetFlagByChar(tempFlag); - - //ConVar Hooks - HookConVarChange(g_cvarEnable,SMLib_ConVarChange); - HookConVarChange(g_cvarDebug,SMLib_ConVarChange); - HookConVarChange(g_cvarDeveloper_Flag,SMLib_ConVarChange); - - Server_PrintDebug(cvarVersionInfo); +* Initialize SMLib's Plugin Manager +* +* @param prefix Prefix for console variables. +* @param tag Tag to used when printing text. +* @param loadTranslations When true translation file will be loaded (SetFailState will be called on error). Name of translation file has to be .phrases.txt. +* @param autoConfig Loads or creates an auto config file in /cfg/sourcemod/.cfg +* @noreturn +*/ +PluginManager_Initialize(const String:prefix[], const String:tag[]="", bool:loadTranslations=false, bool:autoConfig=true) +{ + Plugin_Handle = GetMyHandle(); + GetPluginInfo(Plugin_Handle, PlInfo_Name, Plugin_Name, sizeof(Plugin_Name)); + GetPluginInfo(Plugin_Handle, PlInfo_Author, Plugin_Author, sizeof(Plugin_Author)); + GetPluginInfo(Plugin_Handle, PlInfo_Description, Plugin_Description, sizeof(Plugin_Description)); + GetPluginInfo(Plugin_Handle, PlInfo_Version, Plugin_Version, sizeof(Plugin_Version)); + GetPluginInfo(Plugin_Handle, PlInfo_URL, Plugin_Url, sizeof(Plugin_Url)); + strcopy(Plugin_Prefix,sizeof(Plugin_Prefix),prefix); + strcopy(Plugin_Tag,sizeof(Plugin_Tag),tag); + GetPluginFilename(Plugin_Handle, Plugin_FileName, sizeof(Plugin_FileName)); + + Format( + Plugin_VersionDescription, + sizeof(Plugin_VersionDescription), + "Version of %s ('%s')", + Plugin_Name, + Plugin_FileName + ); + + decl String:baseFileName[PLATFORM_MAX_PATH]; + File_GetFileName(Plugin_FileName,baseFileName,sizeof(baseFileName)); + + if (loadTranslations) { + decl String:path[PLATFORM_MAX_PATH]; + Format(path, sizeof(path), "%s.phrases", baseFileName); + File_LoadTranslations(path, true); + } + + if (autoConfig) { + AutoExecConfig(true,baseFileName); + } + + Plugin_VersionCvar = PluginManager_CreateConVar("version", Plugin_Version, Plugin_VersionDescription, FCVAR_PLUGIN|FCVAR_DONTRECORD|FCVAR_NOTIFY); + //override old cvar in case of late load (this is needed to kick the engine in the ass, so it'll broadcast its value again) + SetConVarString(Plugin_VersionCvar,Plugin_Version); } - -/**************************************************************** - - - C A L L B A C K F U N C T I O N S - - -****************************************************************/ -public SMLib_ConVarChange(Handle:cvar, const String:oldVal[], const String:newVal[]){ - - - //Setting runtime optimizer - //SMLib ConVars (don't remove) - if(cvar == g_cvarEnable){ - g_iPlugin_Enable = StringToInt(newVal); - } - - else if(cvar == g_cvarDebug){ - g_iPlugin_Debug = StringToInt(newVal); - } - - else if(cvar == g_cvarDeveloper_Flag){ - g_afPlugin_Developer_Flag = Admin_GetFlagByChar(newVal); - } - - //Error Handling (don't remove) - else { - - decl String:cvarName[64]; - GetConVarName(cvar,cvarName,sizeof(cvarName)); - LogError("SMLib_ConVarChange was called because cvar '%s' changed from '%s' to '%s', but there isn't an runtime optimizer!",cvarName,oldVal,newVal); - } +/** +* Creates a new console variable. +* Note: You only enter a name and this function will add the prefix you defined in the initialation automatically. +* The new convar also has FCVAR_PLUGIN as default flag set. +* +* @param name Name of new convar. +* @param defaultValue String containing the default value of new convar. +* @param description Optional description of the convar. +* @param flags Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details. +* @param hasMin Optional boolean that determines if the convar has a minimum value. +* @param min Minimum floating point value that the convar can have if hasMin is true. +* @param hasMax Optional boolean that determines if the convar has a maximum value. +* @param max Maximum floating point value that the convar can have if hasMax is true. +* @return A handle to the newly created convar. If the convar already exists, a handle to it will still be returned. +*/ +stock Handle:PluginManager_CreateConVar(const String:name[], const String:defaultValue[], const String:description[]="", flags=0, bool:hasMin=false, Float:min=0.0, bool:hasMax=false, Float:max=0.0) +{ + flags |= FCVAR_PLUGIN; + + decl String:conVarName[256]; + Format(conVarName, sizeof(conVarName), "%s_%s", Plugin_Prefix, name); + + return CreateConVar(conVarName, defaultValue, description, flags, hasMin, min, hasMax, max); } +/** +* Creates a server-only console command, or hooks an already existing one. Server commands are case sensitive. +* Note: The new command also has FCVAR_PLUGIN as default flag set. +* +* @param cmd Name of the command to hook or create. +* @param callback A function to use as a callback for when the command is invoked. +* @param description Optional description to use for command creation. +* @param minArgs NOT IMPLEMENTED YET +* @param usage NOT IMPLEMENTED YET +* @param flags Optional flags to use for command creation. +* @noreturn +*/ +stock PluginManager_RegServerCmd(const String:name[], SrvCmd:callback, const String:description[]="", minArgs=0, const String:usage[]="", flags=0) +{ + flags |= FCVAR_PLUGIN; + + RegAdminCmd(name, callback, description, flags); +} -/***************************************************************** - - - F U N C T I O N S - - -*****************************************************************/ -Handle:CreateConVarEx(const String:name[], const String:defaultValue[], const String:description[]="", flags=0, bool:hasMin=false, Float:min=0.0, bool:hasMax=false, Float:max=0.0){ - - new String:format[MAX_CONVAR_LENGTH]; - - //if we got no tag, then we dont want a _ (underscore) before our cvar - if(g_sPlugin_Tag[0] == '\0'){ - - Format(format,sizeof(format),"%s_%s",g_sPlugin_Short_Name,name); - } - else { - - Format(format,sizeof(format),"%s_%s_%s",g_sPlugin_Tag,g_sPlugin_Short_Name,name); - } - - return CreateConVar(format,defaultValue,description,flags,hasMin,min,hasMax,max); +/** +* Creates a console command, or hooks an already existing one. Console commands are case sensitive. However, if the command already exists in the game, the a client may enter the command in any case. SourceMod corrects for this automatically, and you should only hook the "real" version of the command. +* Note: The new command also has FCVAR_PLUGIN as default flag set. +* +* @param cmd Name of the command to hook or create. +* @param callback A function to use as a callback for when the command is invoked. +* @param description Optional description to use for command creation. +* @param minArgs NOT IMPLEMENTED YET +* @param usage NOT IMPLEMENTED YET +* @param flags Optional flags to use for command creation. +* @noreturn +*/ +stock PluginManager_RegConsoleCmd(const String:name[], ConCmd:callback, const String:description[]="", minArgs=0, const String:usage[]="", flags=0) +{ + flags |= FCVAR_PLUGIN; + + RegConsoleCmd(name, callback, description, flags); } -enum IsDeveloper{ - - IsDeveloper_Pending = -1, - IsDeveloper_NotDeveloper = 0, - IsDeveloper_Developer = 1 -}; +/** +* Creates a console command as an administrative command. If the command does not exist, it is created. When this command is invoked, the access rights of the player are automatically checked before allowing it to continue. Admin commands are case sensitive from both the client and server. +* Note: The new command also has FCVAR_PLUGIN as default flag set. +* +* @param cmd String containing command to register. +* @param callback A function to use as a callback for when the command is invoked. +* @param adminflags Administrative flags (bitstring) to use for permissions. +* @param description Optional description to use for help. +* @param minArgs NOT IMPLEMENTED YET +* @param usage NOT IMPLEMENTED YET +* @param group String containing the command group to use. If empty, the plugin's filename will be used instead. +* @param flags Optional console flags. +* @noreturn +*/ +stock PluginManager_RegAdminCmd(const String:name[], ConCmd:callback, adminflags, const String:description[]="", minArgs=0, const String:usage[]="", const String:group[]="", flags=0) +{ + flags |= FCVAR_PLUGIN; + + RegAdminCmd(name, callback, adminflags, description, group, flags); +} /** - * Checks if the client is a developer. - * - * @param client client index. - * @return true if client is developer. - */ -stock IsDeveloper:Client_IsDeveloper(client){ - - if(((g_iPlugin_Enable == 0)) || (g_iPlugin_Debug == 0)){ - return IsDeveloper_Pending; - } - - static IsDeveloper:ls_idIsDeveloper[MAXPLAYERS+1] = {IsDeveloper_Pending,...}; - static ls_iClientUserId[MAXPLAYERS+1] = {-1,...}; - static AdminFlag:ls_afLastDevFlag[MAXPLAYERS+1] = {AdminFlag:-1,...}; - - if(ls_afLastDevFlag[client] == g_afPlugin_Developer_Flag){ +* Creates a hook for when a game event is fired. +* +* @param name Name of event. +* @param callback An EventHook function pointer. +* @param mode Optional EventHookMode determining the type of hook. +* @param setFailState Optional boolean, if true a SetFailState triggers, when given event isn't available in the game/mod. +* @return True if event exists and was hooked successfully, false otherwise. +*/ +stock bool:PluginManager_HookEvent(const String:name[], EventHook:callback, EventHookMode:mode=EventHookMode_Post, bool:setFailState=true) +{ + if (!HookEventEx(name, callback, mode)) { - if(GetClientOfUserId(ls_iClientUserId[client]) == client){ - - return ls_idIsDeveloper[client]; + if (setFailState) { + SetFailState("can't hook event '%s'", name); } - } - - ls_afLastDevFlag[client] = g_afPlugin_Developer_Flag; - - if(!IsClientAuthorized(client)){ - return IsDeveloper_Pending; - } - - new AdminId:adminid = GetUserAdmin(client); - ls_iClientUserId[client] = GetClientUserId(client); - - if(adminid == INVALID_ADMIN_ID){ - - //PrintToChat(client,"you are not admin at all"); - //PrintToServer("client: %N is not admin at all",client); - return ls_idIsDeveloper[client] = IsDeveloper_NotDeveloper; - } - else if(GetAdminFlag(adminid,g_afPlugin_Developer_Flag)){ - - //PrintToServer("client: %N is in developermode now (g_afPlugin_Developer_Flag: %d)",client,g_afPlugin_Developer_Flag); - return ls_idIsDeveloper[client] = IsDeveloper_Developer; - } - - //PrintToChat(client,"you don't have permission to be developer"); - //PrintToServer("client: %N has not the permission to be developer (g_afPlugin_Developer_Flag: %d)",client,g_afPlugin_Developer_Flag); - return ls_idIsDeveloper[client] = IsDeveloper_NotDeveloper; -} -/** - * Prints a message to the server console if debug mode is on. - * - * @param format Formatting rules. - * @param ... Variable number of format parameters. - * @noreturn - */ -stock Server_PrintDebug(const String:format[],any:...){ - - if(g_iPlugin_Enable == 0){ - return; + return false; } - switch(g_iPlugin_Debug){ - - case 1:{ - decl String:vformat[1024]; - VFormat(vformat, sizeof(vformat), format, 2); - PrintToServer(vformat); - } - case 2:{ - decl String:vformat[1024]; - VFormat(vformat, sizeof(vformat), format, 2); - PrintToServer(vformat); - ClientAll_PrintDebug(vformat); - } - case 3:{ - decl String:vformat[1024]; - VFormat(vformat, sizeof(vformat), format, 2); - PrintToServer(vformat); - PrintToChatAll(vformat); - } - } + return true; } + /** - * Prints a message to all developers if debug mode is on. - * - * @param format Formatting rules. - * @param ... Variable number of format parameters. - * @noreturn - */ -stock ClientAll_PrintDebug(const String:format[],any:...){ - - if(g_iPlugin_Enable == 0){ - return; - } - - switch(g_iPlugin_Debug){ +* Searches for a console variable. +* +* @param name Name of convar to find. +* @param setFailState Optional boolean, if true a SetFailState triggers, when given convar can't be found. +* @return A handle to the convar if it is found. INVALID_HANDLE otherwise. +*/ +stock Handle:PluginManager_FindConVar(const String:name[], bool:setFailState=true) +{ + new Handle:consoleVariable = FindConVar(name); + + if (consoleVariable == INVALID_HANDLE) { - case 1,2:{ - - decl String:vformat[1024]; - VFormat(vformat, sizeof(vformat), format, 2); - - for(new client=1;client<=MaxClients;client++){ - - if(!IsClientInGame(client)){ - continue; - } - - Client_PrintDebug(client,vformat); - } - } - case 3: { - - decl String:vformat[1024]; - VFormat(vformat, sizeof(vformat), format, 2); - - for(new client=1;client<=MaxClients;client++){ - - if(!IsClientInGame(client)){ - continue; - } - - PrintToChat(client,vformat); - } + if (setFailState) { + SetFailState("console variable '%s' can't be found", name); } - } -} -/** - * Prints a message to the developer if debug mode is on. - * - * @param client Client index. - * @param format Formatting rules. - * @param ... Variable number of format parameters. - * @noreturn - */ -stock Client_PrintDebug(client,const String:format[],any:...){ - - if(g_iPlugin_Enable == 0){ - return; - } - - switch(g_iPlugin_Debug){ - case 1,2:{ - - if(!Client_IsDeveloper(client)){ - return; - } - - decl String:vformat[1024]; - VFormat(vformat, sizeof(vformat), format, 3); - PrintToChat(client,vformat); - } - case 3:{ - - decl String:vformat[1024]; - VFormat(vformat, sizeof(vformat), format, 3); - PrintToChat(client,vformat); - } + return INVALID_HANDLE; } -} - -stock AdminFlag:Admin_GetFlagByChar(const String:c[]){ - - new AdminFlag:admflag; - //PrintToChatAll("getflagbychar: input: %s",c); - - if(FindFlagByChar(c[0],admflag)){ - - //PrintToChatAll("getflagbychar: output: %d",admflag); - return admflag; - } - //PrintToChatAll("getflagbychar: output: -1"); - return AdminFlag:-1; + return consoleVariable; } diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/sql.inc b/gameserver/addons/sourcemod/scripting/include/smlib/sql.inc index 7e39932..8bc8ca6 100644 --- a/gameserver/addons/sourcemod/scripting/include/smlib/sql.inc +++ b/gameserver/addons/sourcemod/scripting/include/smlib/sql.inc @@ -29,7 +29,7 @@ stock SQL_TQueryF(Handle:database, SQLTCallback:callback, any:data, DBPriority:p decl String:query[16384]; VFormat(query, sizeof(query), format, 6); - SQL_TQuery(database, callback, query, data, DBPrio_Normal); + SQL_TQuery(database, callback, query, data, priority); } /** diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/strings.inc b/gameserver/addons/sourcemod/scripting/include/smlib/strings.inc index 4a3754e..e675db7 100644 --- a/gameserver/addons/sourcemod/scripting/include/smlib/strings.inc +++ b/gameserver/addons/sourcemod/scripting/include/smlib/strings.inc @@ -108,14 +108,9 @@ stock String_ToLower(const String:input[], String:output[], size) size--; new x=0; - while (input[x] != '\0' || x < size) { + while (input[x] != '\0' && x < size) { - if (IsCharUpper(input[x])) { - output[x] = CharToLower(input[x]); - } - else { - output[x] = input[x]; - } + output[x] = CharToLower(input[x]); x++; } @@ -138,15 +133,10 @@ stock String_ToUpper(const String:input[], String:output[], size) size--; new x=0; - while (input[x] != '\0') { + while (input[x] != '\0' && x < size) { + + output[x] = CharToUpper(input[x]); - if (IsCharLower(input[x])) { - output[x] = CharToUpper(input[x]); - } - else { - output[x] = input[x]; - } - x++; } @@ -191,3 +181,49 @@ stock String_GetRandom(String:buffer[], size, length=32, const String:chrs[]="ab buffer[length] = '\0'; } + +/** + * Checks if string str starts with subString. + * + * + * @param str String to check + * @param subString Sub-String to check in str + * @return True if str starts with subString, false otherwise. + */ +stock bool:String_StartsWith(const String:str[], const String:subString[]) +{ + new n = 0; + while (str[n] != '\0' && subString[n] != '\0') { + + if (str[n] != subString[n]) { + return false; + } + + n++; + } + + return true; +} + +/** + * Checks if string str ends with subString. + * + * + * @param str String to check + * @param subString Sub-String to check in str + * @return True if str ends with subString, false otherwise. + */ +stock bool:String_EndsWith(const String:str[], const String:subString[]) +{ + new n_str = strlen(str) - 1; + new n_subString = strlen(subString) - 1; + + while (n_str != 0 && n_subString != 0) { + + if (str[n_str--] != subString[n_subString--]) { + return false; + } + } + + return true; +} diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/teams.inc b/gameserver/addons/sourcemod/scripting/include/smlib/teams.inc index 91defbe..bb6d725 100644 --- a/gameserver/addons/sourcemod/scripting/include/smlib/teams.inc +++ b/gameserver/addons/sourcemod/scripting/include/smlib/teams.inc @@ -20,7 +20,7 @@ #define TEAM_FOUR 5 /* - * If one team is empty its assumed single team mode is enabled. + * If one team is empty its assumed single team mode is enabled and the game won't start. * * @noparam * @return True if one team is empty, false otherwise. @@ -29,8 +29,8 @@ stock bool:Team_HaveAllPlayers(bool:countFakeClients=true) { new teamCount = GetTeamCount(); for (new i=2; i < teamCount; i++) { - - if (Team_GetClientCount(i, countFakeClients) == 0) { + + if (Team_GetClientCount(i, ((countFakeClients) ? CLIENTFILTER_ALL : CLIENTFILTER_NOBOTS)) == 0) { return false; } } diff --git a/gameserver/addons/sourcemod/scripting/include/smlib/weapons.inc b/gameserver/addons/sourcemod/scripting/include/smlib/weapons.inc index 207bcf6..e196bbc 100644 --- a/gameserver/addons/sourcemod/scripting/include/smlib/weapons.inc +++ b/gameserver/addons/sourcemod/scripting/include/smlib/weapons.inc @@ -53,7 +53,7 @@ stock Weapon_IsValid(weapon) if (!IsValidEdict(weapon)) { return false; } - + return Entity_ClassNameMatches(weapon, "weapon_", true); } @@ -207,6 +207,17 @@ stock Weapon_GetPrimaryAmmoType(weapon) return GetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoType"); } +/* + * Sets the primary ammo Type (int offset) + * + * @param weapon Weapon Entity. + * @param type Primary ammo type value. + */ +stock Weapon_SetPrimaryAmmoType(weapon,type) +{ + return SetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoType", type); +} + /* * Gets the secondary ammo Type (int offset) * @@ -218,6 +229,17 @@ stock Weapon_GetSecondaryAmmoType(weapon) return GetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoType"); } +/* + * Sets the secondary ammo Type (int offset) + * + * @param weapon Weapon Entity. + * @param type Secondary ammo type value. + */ +stock Weapon_SetSecondaryAmmoType(weapon,type) +{ + return SetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoType", type); +} + /* * Gets the primary clip count of a weapon. * @@ -286,7 +308,10 @@ stock Weapon_SetClips(weapon, primary, secondary) */ stock Weapon_GetPrimaryAmmoCount(weapon) { - return GetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoCount"); + if(GetEngineVersion() != Engine_CSGO) + return GetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoCount"); + else + return GetEntProp(weapon, Prop_Data, "m_iPrimaryReserveAmmoCount"); } /* @@ -301,7 +326,10 @@ stock Weapon_GetPrimaryAmmoCount(weapon) */ stock Weapon_SetPrimaryAmmoCount(weapon, value) { - SetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoCount", value); + if(GetEngineVersion() != Engine_CSGO) + SetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoCount", value); + else + SetEntProp(weapon, Prop_Data, "m_iPrimaryReserveAmmoCount", value); } /* @@ -315,7 +343,10 @@ stock Weapon_SetPrimaryAmmoCount(weapon, value) */ stock Weapon_GetSecondaryAmmoCount(weapon) { - return GetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoCount"); + if(GetEngineVersion() != Engine_CSGO) + return GetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoCount"); + else + SetEntProp(weapon, Prop_Data, "m_iSecondaryReserveAmmoCount", value); } /* @@ -330,7 +361,10 @@ stock Weapon_GetSecondaryAmmoCount(weapon) */ stock Weapon_SetSecondaryAmmoCount(weapon, value) { - SetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoCount", value); + if(GetEngineVersion() != Engine_CSGO) + SetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoCount", value); + else + SetEntProp(weapon, Prop_Data, "m_iSecondaryReserveAmmoCount", value); } /* diff --git a/gameserver/addons/sourcemod/scripting/include/timer-config_loader.sp b/gameserver/addons/sourcemod/scripting/include/timer-config_loader.sp index cbaee67..9fe3a92 100644 --- a/gameserver/addons/sourcemod/scripting/include/timer-config_loader.sp +++ b/gameserver/addons/sourcemod/scripting/include/timer-config_loader.sp @@ -54,7 +54,6 @@ enum TimerSettings Float:StuckPenaltyTime, bool:AllowMultipleStart, bool:AllowMultipleEnd, - bool:AllowMultipleShortEnd, bool:AllowMultipleBonusStart, bool:AllowMultipleBonusEnd, String:NPC_Path[32], @@ -173,7 +172,6 @@ enum TimerSettings Float:Tier10Scale, //World Record - bool:ShortWrEnable, bool:BonusWrEnable, //Weapons @@ -198,7 +196,10 @@ enum Styles String:StyleQuickCommand[32], String:StyleQuickWrCommand[32], String:StyleQuickBonusWrCommand[32], - String:StyleQuickShortWrCommand[32], + String:StyleQuickBonus2WrCommand[32], + String:StyleQuickBonus3WrCommand[32], + String:StyleQuickBonus4WrCommand[32], + String:StyleQuickBonus5WrCommand[32], String:StyleDesc[128], //HUD @@ -235,6 +236,7 @@ enum Styles Float:StyleHoverScale, Float:StyleMaxSpeed, StyleAntiBhop, + bool:StyleStartZoneAntiBhop, bool:StyleRealBhop, StyleRealBhopMaxFrames, Float:StyleRealBhopFramePenalty, @@ -350,7 +352,6 @@ stock LoadTimerSettings() g_Settings[StuckPenaltyTime] = KvGetFloat(hKv, "stuck_penalty_time", 10.0); g_Settings[AllowMultipleStart] = bool:KvGetNum(hKv, "allow_multiple_start", 0); g_Settings[AllowMultipleEnd] = bool:KvGetNum(hKv, "allow_multiple_end", 0); - g_Settings[AllowMultipleShortEnd] = bool:KvGetNum(hKv, "allow_multiple_shortend", 0); g_Settings[AllowMultipleBonusStart] = bool:KvGetNum(hKv, "allow_multiple_bonusstart", 0); g_Settings[AllowMultipleBonusEnd] = bool:KvGetNum(hKv, "allow_multiple_bonusend", 0); g_Settings[ZoneResize] = KvGetFloat(hKv, "trigger_resize", 16.0); @@ -471,7 +472,6 @@ stock LoadTimerSettings() } else if(StrEqual(sSectionName, "Worldrecord", false)) { - g_Settings[ShortWrEnable] = bool:KvGetNum(hKv, "worldrecord_shortwr_enable", 1); g_Settings[BonusWrEnable] = bool:KvGetNum(hKv, "worldrecord_bonuswr_enable", 1); } else if(StrEqual(sSectionName, "Weapons", false)) @@ -593,6 +593,7 @@ stock LoadPhysics() g_Physics[g_StyleCount][StyleQuakeBhop] = KvGetNum(hKv, "quake_bhop", 0); g_Physics[g_StyleCount][StyleStrafeBoost] = KvGetNum(hKv, "strafe_boost", 0); g_Physics[g_StyleCount][StyleAntiBhop] = KvGetNum(hKv, "anti_bhop", 0); + g_Physics[g_StyleCount][StyleStartZoneAntiBhop] = bool:KvGetNum(hKv, "anti_bhop_start", 0); g_Physics[g_StyleCount][StyleRealBhop] = bool:KvGetNum(hKv, "real_bhop", 0); g_Physics[g_StyleCount][StyleRealBhopMaxFrames] = KvGetNum(hKv, "real_bhop_maxframes", 11); g_Physics[g_StyleCount][StyleRealBhopFramePenalty] = KvGetFloat(hKv, "real_bhop_framepenalty", 0.78); @@ -602,7 +603,10 @@ stock LoadPhysics() KvGetString(hKv, "chat_command", g_Physics[g_StyleCount][StyleQuickCommand], 32); KvGetString(hKv, "chat_wr_command", g_Physics[g_StyleCount][StyleQuickWrCommand], 32); KvGetString(hKv, "chat_bwr_command", g_Physics[g_StyleCount][StyleQuickBonusWrCommand], 32); - KvGetString(hKv, "chat_swr_command", g_Physics[g_StyleCount][StyleQuickShortWrCommand], 32); + KvGetString(hKv, "chat_b2wr_command", g_Physics[g_StyleCount][StyleQuickBonus2WrCommand], 32); + KvGetString(hKv, "chat_b3wr_command", g_Physics[g_StyleCount][StyleQuickBonus3WrCommand], 32); + KvGetString(hKv, "chat_b4wr_command", g_Physics[g_StyleCount][StyleQuickBonus4WrCommand], 32); + KvGetString(hKv, "chat_b5wr_command", g_Physics[g_StyleCount][StyleQuickBonus5WrCommand], 32); KvGetString(hKv, "exec_onfinish", g_Physics[g_StyleCount][StyleOnFinishExec], 128); KvGetString(hKv, "desc", g_Physics[g_StyleCount][StyleDesc], 128); diff --git a/gameserver/addons/sourcemod/scripting/include/timer-mapchooser.inc b/gameserver/addons/sourcemod/scripting/include/timer-mapchooser.inc new file mode 100644 index 0000000..0a9753a --- /dev/null +++ b/gameserver/addons/sourcemod/scripting/include/timer-mapchooser.inc @@ -0,0 +1,106 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * MapChooser Extended + * Creates a map vote at appropriate times, setting sm_nextmap to the winning + * vote + * + * MapChooser Extended (C)2011-2013 Powerlord (Ross Bemrose) + * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#if defined _mapchooser_extended_included_ + #endinput +#endif +#define _mapchooser_extended_included_ +#include + +// MCE 1.9 series + +enum CanNominateResult +{ + CanNominate_No_VoteFull, /** No, nominations list is full */ + CanNominate_No_VoteInProgress, /** No, map vote is in progress */ + CanNominate_No_VoteComplete, /** No, map vote is completed */ + CanNominate_Yes, /** Yes, you can nominate */ +}; + + +/** + * Called whenever warning timer starts + * + */ +forward OnMapVoteWarningStart(); + +/** + * Called whenever runoff warning timer starts + */ +forward OnMapVoteRunnoffWarningStart(); + +/** + * Called whenever the timer ticks + */ +forward OnMapVoteWarningTick(time); + +/** + * Called whenever vote starts + * + * @deprecated Will be removed in MapChooser 1.8. Use OnMapVoteStarted instead. + */ +forward OnMapVoteStart(); + +/** + * Called whenever vote ends + */ +forward OnMapVoteEnd(const String:map[]); + +/** + * Is a map on the current game's official list? + * This should be treated as informative only. + * + * @param map Name of map to check + * @return true if it's on the list of official maps for this game + */ +native bool:IsMapOfficial(const String:map[]); + +/** + * Is nominate allowed? + * + * @return A CanNominateResult corresponding to whether a vote is allowed or not + */ +native CanNominateResult:CanNominate(); + +public SharedPlugin:__pl_mapchooser_extended = +{ + name = "mapchooser", + file = "mapchooser_extended.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; diff --git a/gameserver/addons/sourcemod/scripting/include/timer-mapzones.inc b/gameserver/addons/sourcemod/scripting/include/timer-mapzones.inc index 8205af3..2ed6335 100644 --- a/gameserver/addons/sourcemod/scripting/include/timer-mapzones.inc +++ b/gameserver/addons/sourcemod/scripting/include/timer-mapzones.inc @@ -8,8 +8,16 @@ #define LEVEL_END 999 #define LEVEL_BONUS_START 1001 #define LEVEL_BONUS_END 1999 - -// 38 zones types +#define LEVEL_BONUS2_START 2001 +#define LEVEL_BONUS2_END 2999 +#define LEVEL_BONUS3_START 3001 +#define LEVEL_BONUS3_END 3999 +#define LEVEL_BONUS4_START 4001 +#define LEVEL_BONUS4_END 4999 +#define LEVEL_BONUS5_START 5001 +#define LEVEL_BONUS5_END 5999 + +// 60 zones types enum MapZoneType { ZtStart, //0 @@ -39,7 +47,7 @@ enum MapZoneType ZtNoBoost, //24 ZtRestartNormalTimer, //25 ZtRestartBonusTimer, //26 - ZtShortEnd, //27 + ZtShortEnd, //27 - Removed ZtPushNorth, //28 ZtPushSouth, //29 ZtPushWest, //30 @@ -55,7 +63,25 @@ enum MapZoneType ZtBlockAttack, //40 ZtCheckpoint, //41 ZtBonusCheckpoint, //42 - ZtAntiNoclip //43 + ZtAntiNoclip, //43 + ZtBonus2Start, //44 + ZtBonus2End, //45 + ZtBonus2Level, //46 + ZtBonus2Checkpoint, //47 + ZtBonus3Start, //48 + ZtBonus3End, //49 + ZtBonus3Level, //50 + ZtBonus3Checkpoint, //51 + ZtBonus4Start, //52 + ZtBonus4End, //53 + ZtBonus4Level, //54 + ZtBonus4Checkpoint, //55 + ZtBonus5Start, //56 + ZtBonus5End, //57 + ZtBonus5Level, //58 + ZtBonus5Checkpoint, //59 + ZtBhop, //60 + ZtAntiCp //61 } /* Forwards */ @@ -217,4 +243,11 @@ public __pl_timer_mapzones_SetNTVOptional() { MarkNativeAsOptional("Timer_SetIgnoreEndTouchStart"); MarkNativeAsOptional("Timer_IsPlayerTouchingZoneType"); MarkNativeAsOptional("Timer_GetMapzoneCount"); +} + +stock bool:Timer_IsPlayerTouchingStartZone(client) +{ + if(Timer_IsPlayerTouchingZoneType(client, ZtStart) || Timer_IsPlayerTouchingZoneType(client, ZtBonusStart) || Timer_IsPlayerTouchingZoneType(client, ZtBonus2Start) || Timer_IsPlayerTouchingZoneType(client, ZtBonus3Start) || Timer_IsPlayerTouchingZoneType(client, ZtBonus4Start) || Timer_IsPlayerTouchingZoneType(client, ZtBonus5Start)) + return true; + return false; } \ No newline at end of file diff --git a/gameserver/addons/sourcemod/scripting/include/timer-physics.inc b/gameserver/addons/sourcemod/scripting/include/timer-physics.inc index 90b4829..5c07e62 100644 --- a/gameserver/addons/sourcemod/scripting/include/timer-physics.inc +++ b/gameserver/addons/sourcemod/scripting/include/timer-physics.inc @@ -42,6 +42,9 @@ native Timer_GetCurrentSpeed(client, &Float:speed); native Timer_GetMaxSpeed(client, &Float:maxspeed); native Timer_GetAvgSpeed(client, &Float:avgspeed); native Timer_ResetAccuracy(client); + +native Timer_SaveLastJumps(client); +native Timer_RestoreLastJumps(client); public SharedPlugin:__pl_timer_physics = { @@ -64,4 +67,6 @@ public __pl_timer_physics_SetNTVOptional() MarkNativeAsOptional("Timer_GetMaxSpeed"); MarkNativeAsOptional("Timer_GetAvgSpeed"); MarkNativeAsOptional("Timer_ResetAccuracy"); + MarkNativeAsOptional("Timer_SaveLastJumps"); + MarkNativeAsOptional("Timer_RestoreLastJumps"); } \ No newline at end of file diff --git a/gameserver/addons/sourcemod/scripting/include/timer.inc b/gameserver/addons/sourcemod/scripting/include/timer.inc index 6351413..9f17d4f 100644 --- a/gameserver/addons/sourcemod/scripting/include/timer.inc +++ b/gameserver/addons/sourcemod/scripting/include/timer.inc @@ -5,15 +5,15 @@ #pragma semicolon 1 -#define PL_VERSION "2.3.0.0" +#define PL_VERSION "2.5.0.0" /*** SETTINGS ***/ //Uncomment this to use colors.inc and disable morecolors.inc -//#define LEGACY_COLORS "CS:GO Color Support" +#define LEGACY_COLORS "CS:GO Color Support" #define MAX_STYLES 16 //Max number of styles (default 32 ID:0-31) -#define MAX_TRACKS 10 +#define MAX_TRACKS 6 // Normal+Bonus1-5 //Max. number of door/button based bhop blocks handled in a map #define MAX_BHOPBLOCKS 1024 @@ -23,7 +23,10 @@ //Tracks #define TRACK_NORMAL 0 #define TRACK_BONUS 1 -#define TRACK_SHORT 2 +#define TRACK_BONUS2 2 +#define TRACK_BONUS3 3 +#define TRACK_BONUS4 4 +#define TRACK_BONUS5 5 //Colors Includes #if defined LEGACY_COLORS @@ -53,11 +56,6 @@ #define SPECMODE_3RDPERSON 5 #define SPECMODE_FREELOOK 6 -//Start commands -#define SCMD_START 0 -#define SCMD_RESTART 1 -#define SCMD_BONUSSTART 2 - //Func_ Flags #define SF_BUTTON_DONTMOVE (1<<0) //dont move when fired (func_button) #define SF_BUTTON_TOUCH_ACTIVATES (1<<8) //button fires when touched (func_button) diff --git a/gameserver/addons/sourcemod/scripting/simple-chatprocessor.sp b/gameserver/addons/sourcemod/scripting/simple-chatprocessor.sp index 4dc9e62..33a59bc 100644 --- a/gameserver/addons/sourcemod/scripting/simple-chatprocessor.sp +++ b/gameserver/addons/sourcemod/scripting/simple-chatprocessor.sp @@ -34,6 +34,8 @@ $Copyright: (c) Simple Plugins 2008-2009$ ************************************************************************* */ +#pragma dynamic 131072 + #include #define PLUGIN_VERSION "2.0.2 (modified by Zipcore)" diff --git a/gameserver/addons/sourcemod/scripting/timer-core.sp b/gameserver/addons/sourcemod/scripting/timer-core.sp index b341cb2..2b61206 100644 --- a/gameserver/addons/sourcemod/scripting/timer-core.sp +++ b/gameserver/addons/sourcemod/scripting/timer-core.sp @@ -47,7 +47,6 @@ enum Timer CurrentStyle, FpsMax, Track, - bool:ShortEndReached, String:ReplayFile[32] } @@ -289,6 +288,14 @@ public OnMapStart() LoadPhysics(); LoadTimerSettings(); + + for (new client = 1; client <= MaxClients; client++) + g_timers[client][Track] = TRACK_NORMAL; +} + +public OnClientPutInServer(client) +{ + g_timers[client][Track] = TRACK_NORMAL; } /** @@ -411,7 +418,6 @@ bool:ResetTimer(client) g_timers[client][IsPaused] = false; g_timers[client][PauseStartTime] = 0.0; g_timers[client][PauseTotalTime] = 0.0; - g_timers[client][ShortEndReached] = false; g_timers[client][ReplayFile][0] = '\0'; if(g_timerPhysics) Timer_ResetAccuracy(client); @@ -434,7 +440,6 @@ bool:StartTimer(client) return false; g_timers[client][Enabled] = true; - g_timers[client][ShortEndReached] = false; g_timers[client][StartTime] = GetGameTime(); g_timers[client][EndTime] = -1.0; g_timers[client][Jumps] = 0; @@ -470,7 +475,6 @@ bool:StopTimer(client, bool:stopPaused = true) //Get time g_timers[client][Enabled] = false; - g_timers[client][ShortEndReached] = true; g_timers[client][EndTime] = GetGameTime(); //Prevent Resume @@ -551,7 +555,7 @@ bool:PauseTimer(client) Array_Copy(angles, g_timers[client][PauseLastAngles], 3); new Float:velocity[3]; - GetClientAbsVelocity(client, velocity); + GetEntPropVector(client, Prop_Data, "m_vecVelocity", velocity); Array_Copy(velocity, g_timers[client][PauseLastVelocity], 3); Call_StartForward(g_timerPausedForward); @@ -695,11 +699,7 @@ FinishRound(client, const String:map[], Float:time, jumps, style, fpsmax, track) if(g_timerPhysics) if (g_Physics[style][StyleCategory] != MCategory_Ranked || !(bool:Timer_IsStyleRanked(style))) return; - - //short end already triggered - if (g_timers[client][ShortEndReached] && track == 2) - return; - + new flashbangcount; //TODO new stage; @@ -725,9 +725,7 @@ FinishRound(client, const String:map[], Float:time, jumps, style, fpsmax, track) return; } } - - if(track == TRACK_SHORT) g_timers[client][ShortEndReached] = true; - + //Record Info new RecordId; new Float:RecordTime; diff --git a/gameserver/addons/sourcemod/scripting/timer-cpmod.sp b/gameserver/addons/sourcemod/scripting/timer-cpmod.sp index cd932f6..bfab741 100644 --- a/gameserver/addons/sourcemod/scripting/timer-cpmod.sp +++ b/gameserver/addons/sourcemod/scripting/timer-cpmod.sp @@ -6,6 +6,7 @@ #undef REQUIRE_PLUGIN #include #include +#include #include #undef REQUIRE_EXTENSIONS diff --git a/gameserver/addons/sourcemod/scripting/timer-finish_msg_csgo.sp b/gameserver/addons/sourcemod/scripting/timer-finish_msg_csgo.sp index 950c049..7e8f4a0 100644 --- a/gameserver/addons/sourcemod/scripting/timer-finish_msg_csgo.sp +++ b/gameserver/addons/sourcemod/scripting/timer-finish_msg_csgo.sp @@ -84,112 +84,110 @@ public OnTimerRecord(client, track, style, Float:time, Float:lasttime, currentra { decl String:name[MAX_NAME_LENGTH]; GetClientName(client, name, sizeof(name)); - + + //General Info + new Float:fWrTime; + new iTotalRanks; + //Record Info - new RecordId; - new Float:RecordTime; - new RankTotal; - new Float:LastTime; - new Float:LastTimeStatic; - new LastJumps; - decl String:TimeDiff[32]; - decl String:buffer[32]; - - new bool:NewPersonalRecord = false; - new bool:NewWorldRecord = false; - new bool:FirstRecord = false; - - new bool:ranked, Float:jumpacc; - if(g_timerPhysics) + decl String:sTime[64]; + + new Float:fTimeDiff; + new iStrafeCount; + new Float:fJumpAcc; + new bool:bRankedStyle; + + new bool:bNewPersonalRecord; + new bool:bNewWorldRecord; + new bool:bFirstRecord; + new bool:bOnlyTimeImproved; + + // Core + new bool:enabled = false, jumps, fpsmax; + Timer_SecondsToTime(time, sTime, sizeof(sTime), 2); + new Float:fTimeOld; + Timer_GetClientTimer(client, enabled, fTimeOld, jumps, fpsmax); + + // Physics + if(g_timerPhysics) { - ranked = bool:Timer_IsStyleRanked(style); - Timer_GetJumpAccuracy(client, jumpacc); + bRankedStyle = bool:Timer_IsStyleRanked(style); + Timer_GetJumpAccuracy(client, fJumpAcc); } - - new strafes; - if(g_timerStrafes) strafes = Timer_GetStrafeCount(client); - - new bool:enabled = false; - new jumps = 0; - new fpsmax; + // Strafes + if(g_timerStrafes) + { + iStrafeCount = Timer_GetStrafeCount(client); + } - Timer_GetClientTimer(client, enabled, time, jumps, fpsmax); - - if(g_timerWorldRecord) + if(g_timerWorldRecord) { /* Get Personal Record */ - if(Timer_GetBestRound(client, style, track, LastTime, LastJumps)) + if(lasttime > 0.0) { - LastTimeStatic = LastTime; - LastTime -= time; - if(LastTime < 0.0) - { - LastTime *= -1.0; - Timer_SecondsToTime(LastTime, buffer, sizeof(buffer), 3); - FormatEx(TimeDiff, sizeof(TimeDiff), "+%s", buffer); - } - else if(LastTime > 0.0) - { - Timer_SecondsToTime(LastTime, buffer, sizeof(buffer), 3); - FormatEx(TimeDiff, sizeof(TimeDiff), "-%s", buffer); - } - else if(LastTime == 0.0) - { - Timer_SecondsToTime(LastTime, buffer, sizeof(buffer), 3); - FormatEx(TimeDiff, sizeof(TimeDiff), "%s", buffer); - } + fTimeDiff = lasttime-time; + + if(fTimeDiff < 0.0) + fTimeDiff *= -1.0; } else { //No personal record, this is his first record - FirstRecord = true; - LastTime = 0.0; - Timer_SecondsToTime(LastTime, buffer, sizeof(buffer), 3); - FormatEx(TimeDiff, sizeof(TimeDiff), "%s", buffer); - RankTotal++; + bFirstRecord = true; + fTimeDiff = 0.0; + iTotalRanks++; } } - - decl String:TimeString[32]; - Timer_SecondsToTime(time, TimeString, sizeof(TimeString), 2); - - new String:WrName[32], String:WrTime[32]; - new Float:wrtime; - - if(g_timerWorldRecord) + + new String:sBeatenName[32], String:sBeatenTime[32]; + new Float:fBeatenTime; + + if(g_timerWorldRecord) { - Timer_GetRecordTimeInfo(style, track, newrank, wrtime, WrTime, 32); - Timer_GetRecordHolderName(style, track, newrank, WrName, 32); - + Timer_GetRecordTimeInfo(style, track, newrank, fBeatenTime, sBeatenTime, 32); + Timer_GetRecordHolderName(style, track, newrank, sBeatenName, 32); + /* Get World Record */ - Timer_GetStyleRecordWRStats(style, track, RecordId, RecordTime, RankTotal); + new RecordId; + Timer_GetStyleRecordWRStats(style, track, RecordId, fWrTime, iTotalRanks); } + new Float:fWRDiffTime; + new String:sWrDiffTime[32]; + + fWRDiffTime = time-fWrTime; + Timer_SecondsToTime(fWRDiffTime, sWrDiffTime, sizeof(sWrDiffTime), 2); + + if(fWrTime <= 0.0) + Format(sWrDiffTime, sizeof(sWrDiffTime), "-%s", sWrDiffTime); + else if(fWrTime <= time) + Format(sWrDiffTime, sizeof(sWrDiffTime), "+%s", sWrDiffTime); + else Format(sWrDiffTime, sizeof(sWrDiffTime), "-%s", sWrDiffTime); + + //PrintToChat(client, "[DEBUG] %.2f - %.2f = %.2f", time, fWrTime, fWRDiffTime); + //PrintToChat(client, "[DEBUG] %s", sWrDiffTime); + /* Detect Record Type */ - if(RecordTime == 0.0 || time < RecordTime) + if(fWrTime == 0.0 || time < fWrTime) { - NewWorldRecord = true; + bNewWorldRecord = true; } - - if(LastTimeStatic == 0.0 || time < LastTimeStatic) + + if(lasttime == 0.0 || time < lasttime) { - NewPersonalRecord = true; + bNewPersonalRecord = true; } - - new bool:self = false; - + if(currentrank == newrank) - { - self = true; - } - - if(FirstRecord) RankTotal++; - - new Float:wrdiff = time-wrtime; - + bOnlyTimeImproved = true; + + if(bFirstRecord) iTotalRanks++; + + new Float:fBeatenTimeDiff = time-fBeatenTime; + new String:BonusString[32]; - + if(track == TRACK_BONUS) { FormatEx(BonusString, sizeof(BonusString), " {olive}bonus"); @@ -210,82 +208,79 @@ public OnTimerRecord(client, track, style, Float:time, Float:lasttime, currentra { FormatEx(BonusString, sizeof(BonusString), " {olive}bonus5"); } - + new String:RankString[128], String:RankPwndString[128]; - new String:JumpString[128]; + new String:sJumps[128]; new bool:bAll = false; - + new String:StyleString[128]; - if(g_Settings[MultimodeEnable]) + if(g_Settings[MultimodeEnable]) FormatEx(StyleString, sizeof(StyleString), " on {olive}%s", g_Physics[style][StyleName]); - - if(NewWorldRecord) + + if(bNewWorldRecord) { bAll = true; - FormatEx(RankString, sizeof(RankString), "{purple}NEW WORLD RECORD"); - - if(wrtime > 0.0) + FormatEx(RankString, sizeof(RankString), "{purple} NEW MAP RECORD"); + + if(fBeatenTime > 0.0) { - if(self) - FormatEx(RankPwndString, sizeof(RankPwndString), "{olive}Improved {lightred}%s{olive}! {lightred}[%.2fs]{olive} diff, old time was {lightred}[%s]", "himself", wrdiff, WrTime); + if(bOnlyTimeImproved) + FormatEx(RankPwndString, sizeof(RankPwndString), "{olive}Improved {lightred}%s{olive}! {lightred}[%.2fs]{olive} diff, old time was {lightred}[%s]", "himself", fBeatenTimeDiff, sBeatenTime); else - FormatEx(RankPwndString, sizeof(RankPwndString), "{olive}Beaten {lightred}%s{olive}! {lightred}[%.2fs]{olive} diff, old time was {lightred}[%s]", WrName, wrdiff, WrTime); + FormatEx(RankPwndString, sizeof(RankPwndString), "{olive}Beaten {lightred}%s{olive}! {lightred}[%.2fs]{olive} diff, old time was {lightred}[%s]", sBeatenName, fBeatenTimeDiff, sBeatenTime); } } - else if(newrank > 5000) - { - FormatEx(RankString, sizeof(RankString), "{lightred}#%d+ / %d", newrank, RankTotal); - } - else if(NewPersonalRecord || FirstRecord) + else if(bNewPersonalRecord || bFirstRecord) { bAll = true; - FormatEx(RankString, sizeof(RankString), "{lightred}#%d / %d", newrank, RankTotal); - - if(newrank < currentrank) FormatEx(RankPwndString, sizeof(RankPwndString), "{olive}Beaten {lightred}%s{olive}! {lightred}[%.2fs]{olive} diff, old time was {lightred}[%s]", WrName, wrdiff, WrTime); - } - else if(NewPersonalRecord) + FormatEx(RankString, sizeof(RankString), "{lightred}#%d / %d", newrank, iTotalRanks); + + if(newrank < currentrank) + FormatEx(RankPwndString, sizeof(RankPwndString), "{olive}Beaten {lightred}%s{olive}! {lightred}[%.2fs]{olive} diff, old time was {lightred}[%s]", sBeatenName, fBeatenTimeDiff, sBeatenTime); + } + else if(bNewPersonalRecord) { - FormatEx(RankString, sizeof(RankString), "{orange}#%d / %d", newrank, RankTotal); - - Format(RankPwndString, sizeof(RankPwndString), "You have improved {lightred}yourself! {lightred}[%.2fs]{olive} diff, old time was {lightred}[%s]", wrdiff, WrTime); + FormatEx(RankString, sizeof(RankString), "{orange}#%d / %d", newrank, iTotalRanks); + + Format(RankPwndString, sizeof(RankPwndString), "You have improved {lightred}yourself! {lightred}[%.2fs]{olive} diff, old time was {lightred}[%s]", fBeatenTimeDiff, sBeatenTime); } - + if(g_Settings[JumpsEnable]) { - FormatEx(JumpString, sizeof(JumpString), "{olive} and {lightred}%d jumps [%.2f ⁰⁄₀]", jumps, jumpacc); + FormatEx(sJumps, sizeof(sJumps), "{olive} and {lightred}%d jumps [%.2f ⁰⁄₀]", jumps, fJumpAcc); } - - if(g_Settings[StrafesEnable]) + + if(g_Settings[StrafesEnable] && g_timerStrafes) { - FormatEx(JumpString, sizeof(JumpString), "{olive} and {lightred}%d strafes", strafes); + FormatEx(sJumps, sizeof(sJumps), "{olive} and {lightred}%d strafes", iStrafeCount); } - - if(ranked) + + if(bRankedStyle) { - if(FirstRecord || NewPersonalRecord) + if(bFirstRecord || bNewPersonalRecord) { if(bAll) { - CPrintToChatAll("%s {olive}Player {lightred}%s{olive} has finished%s{olive}%s{olive}.", PLUGIN_PREFIX2, name, BonusString, StyleString); - CPrintToChatAll("{olive}Time: {lightred}[%ss] %s %s", TimeString, JumpString, RankString); + CPrintToChatAll("%s {lightred}%s{olive} has finished%s{olive}%s{olive}.", PLUGIN_PREFIX2, name, BonusString, StyleString); + CPrintToChatAll("{olive}Time: {lightred}%ss (WR %s) %s %s", sTime, sWrDiffTime, sJumps, RankString); CPrintToChatAll("%s", RankPwndString); } else { CPrintToChat(client, "%s {lightred}You{olive} have finished%s{olive}%s{olive}.", PLUGIN_PREFIX2, BonusString, StyleString); - CPrintToChat(client, "{olive}Time: {lightred}[%ss] %s %s", TimeString, JumpString, RankString); + CPrintToChat(client, "{olive}Time: {lightred}%ss (WR %s) %s %s", sTime, sWrDiffTime, sJumps, RankString); CPrintToChat(client, "%s", RankPwndString); } } else { - CPrintToChat(client, "%s {lightred}You{olive} have finished%s{olive}%s{olive}. Time: {lightred}[%ss] %s %s", PLUGIN_PREFIX2, BonusString, StyleString, TimeString, JumpString, RankString); + CPrintToChat(client, "%s {lightred}You{olive} have finished%s{olive}%s{olive}. Time: {lightred}%ss (WR %s) %s %s", PLUGIN_PREFIX2, BonusString, StyleString, sTime, sWrDiffTime, sJumps, RankString); } } else { CPrintToChat(client, "{lightred}You{olive} have finished%s{olive}%s{olive}.", PLUGIN_PREFIX2, BonusString, StyleString); - CPrintToChat(client, "{olive}Time: {lightred}[%ss] %s", TimeString, JumpString); + CPrintToChat(client, "{olive}Time: {lightred}[%ss] %s", sTime, sJumps); } } diff --git a/gameserver/addons/sourcemod/scripting/timer-finish_msg_css.sp b/gameserver/addons/sourcemod/scripting/timer-finish_msg_css.sp index 521182f..9285e5b 100644 --- a/gameserver/addons/sourcemod/scripting/timer-finish_msg_css.sp +++ b/gameserver/addons/sourcemod/scripting/timer-finish_msg_css.sp @@ -14,7 +14,7 @@ new bool:g_timerPhysics = false; new bool:g_timerWorldRecord = false; -public Plugin:myinfo = +public Plugin:myinfo = { name = "[Timer] Finish Message", author = "Zipcore", @@ -31,10 +31,10 @@ public OnPluginStart() SetFailState("Check timer error logs."); return; } - + LoadPhysics(); LoadTimerSettings(); - + g_timerPhysics = LibraryExists("timer-physics"); g_timerWorldRecord = LibraryExists("timer-worldrecord"); } @@ -44,7 +44,7 @@ public OnLibraryAdded(const String:name[]) if (StrEqual(name, "timer-physics")) { g_timerPhysics = true; - } + } else if (StrEqual(name, "timer-worldrecord")) { g_timerWorldRecord = true; @@ -52,11 +52,11 @@ public OnLibraryAdded(const String:name[]) } public OnLibraryRemoved(const String:name[]) -{ +{ if (StrEqual(name, "timer-physics")) { g_timerPhysics = false; - } + } else if (StrEqual(name, "timer-worldrecord")) { g_timerWorldRecord = false; @@ -74,7 +74,7 @@ public OnTimerRecord(client, track, style, Float:time, Float:lasttime, currentra { decl String:name[MAX_NAME_LENGTH]; GetClientName(client, name, sizeof(name)); - + //Record Info new RecordId; new Float:RecordTime; @@ -84,30 +84,30 @@ public OnTimerRecord(client, track, style, Float:time, Float:lasttime, currentra new LastJumps; decl String:TimeDiff[32]; decl String:buffer[32]; - + new bool:NewPersonalRecord = false; new bool:NewWorldRecord = false; new bool:FirstRecord = false; - + new bool:ranked; - if(g_timerPhysics) + if(g_timerPhysics) { ranked = bool:Timer_IsStyleRanked(style); } - + new bool:enabled = false; new jumps = 0; new fpsmax; Timer_GetClientTimer(client, enabled, time, jumps, fpsmax); - - if(g_timerWorldRecord) + + if(g_timerWorldRecord) { /* Get Personal Record */ if(Timer_GetBestRound(client, style, track, LastTime, LastJumps)) { LastTimeStatic = LastTime; - LastTime -= time; + LastTime -= time; if(LastTime < 0.0) { LastTime *= -1.0; @@ -135,72 +135,84 @@ public OnTimerRecord(client, track, style, Float:time, Float:lasttime, currentra RankTotal++; } } - + decl String:TimeString[32]; Timer_SecondsToTime(time, TimeString, sizeof(TimeString), 2); - + new String:WrName[32], String:WrTime[32]; new Float:wrtime; - + if(g_timerWorldRecord) { Timer_GetRecordTimeInfo(style, track, newrank, wrtime, WrTime, 32); Timer_GetRecordHolderName(style, track, newrank, WrName, 32); - + /* Get World Record */ Timer_GetStyleRecordWRStats(style, track, RecordId, RecordTime, RankTotal); } - + /* Detect Record Type */ if(RecordTime == 0.0 || time < RecordTime) { NewWorldRecord = true; } - + if(LastTimeStatic == 0.0 || time < LastTimeStatic) { NewPersonalRecord = true; } - + new bool:self = false; - + if(currentrank == newrank) { self = true; } - + if(FirstRecord) RankTotal++; - + new Float:wrdiff = time-wrtime; - + new String:BonusString[32]; - + if(track == TRACK_BONUS) { FormatEx(BonusString, sizeof(BonusString), " {green}[Bonus]"); } - else if(track == TRACK_SHORT) + else if(track == TRACK_BONUS2) + { + FormatEx(BonusString, sizeof(BonusString), " {green}bonus2"); + } + else if(track == TRACK_BONUS3) { - FormatEx(BonusString, sizeof(BonusString), " {green}[Short]"); - } - + FormatEx(BonusString, sizeof(BonusString), " {green}bonus3"); + } + else if(track == TRACK_BONUS4) + { + FormatEx(BonusString, sizeof(BonusString), " {green}bonus4"); + } + else if(track == TRACK_BONUS5) + { + FormatEx(BonusString, sizeof(BonusString), " {green}bonus5"); + } + new String:RankString[128], String:RankPwndString[128]; new bool:bAll = false; - + decl String:StyleString[128]; - + if(g_StyleCount > 0 && !g_Settings[MultimodeEnable]) FormatEx(StyleString, sizeof(StyleString), " {green}[%s]", g_Physics[style][StyleName]); - - if(g_Settings[MultimodeEnable]) + + if(g_Settings[MultimodeEnable]) FormatEx(StyleString, sizeof(StyleString), " {green}[%s]", g_Physics[style][StyleName]); - + if(NewWorldRecord) { bAll = true; FormatEx(RankString, sizeof(RankString), "\n{magenta}New WR!"); - + if(wrtime > 0.0) { if(self) @@ -217,16 +229,16 @@ public OnTimerRecord(client, track, style, Float:time, Float:lasttime, currentra { bAll = true; FormatEx(RankString, sizeof(RankString), "{yellow}#%d/%d", newrank, RankTotal); - + if(newrank < currentrank) Format(RankPwndString, sizeof(RankPwndString), "{blue}Beaten {blue}%s{blue}! {yellow}[%s]{blue} by {yellow}[%.2fs]", WrName, WrTime, wrdiff); - } + } else if(NewPersonalRecord) { FormatEx(RankString, sizeof(RankString), "{orange}#%d/%d", newrank, RankTotal); - + FormatEx(RankPwndString, sizeof(RankPwndString), "You have improved yourself! {yellow}[%s]{blue} by {yellow}[%.2fs]", WrTime, wrdiff); } - + if(ranked) { if(FirstRecord) diff --git a/gameserver/addons/sourcemod/scripting/timer-hud_csgo.sp b/gameserver/addons/sourcemod/scripting/timer-hud_csgo.sp index b0fe07c..8dbc0fc 100644 --- a/gameserver/addons/sourcemod/scripting/timer-hud_csgo.sp +++ b/gameserver/addons/sourcemod/scripting/timer-hud_csgo.sp @@ -109,35 +109,35 @@ public OnPluginStart() SetFailState("Check timer error logs."); return; } - + g_timerPhysics = LibraryExists("timer-physics"); g_timerMapzones = LibraryExists("timer-mapzones"); g_timerLjStats = LibraryExists("timer-ljstats"); g_timerRankings = LibraryExists("timer-rankings"); g_timerWorldRecord = LibraryExists("timer-worldrecord"); - + LoadPhysics(); LoadTimerSettings(); - + LoadTranslations("timer.phrases"); - - if(g_Settings[HUDMasterEnable]) + + if(g_Settings[HUDMasterEnable]) { HookEvent("player_jump", Event_PlayerJump); - + HookEvent("player_death", Event_Reset); HookEvent("player_team", Event_Reset); HookEvent("player_spawn", Event_Reset); HookEvent("player_disconnect", Event_Reset); - + RegConsoleCmd("sm_hidemyass", Cmd_HideMyAss); RegConsoleCmd("sm_hud", MenuHud); RegConsoleCmd("sm_specinfo", Cmd_SpecInfo); - + g_cvarTimeLimit = FindConVar("mp_timelimit"); - + AutoExecConfig(true, "timer/timer-hud"); - + //cookies yummy :) cookieHudPref = RegClientCookie("timer_hud_master", "Turn on or off all hud components", CookieAccess_Private); cookieHudMainPref = RegClientCookie("timer_hud_main", "Turn on or off main hud components", CookieAccess_Private); @@ -167,11 +167,11 @@ public OnLibraryAdded(const String:name[]) if (StrEqual(name, "timer-physics")) { g_timerPhysics = true; - } + } else if (StrEqual(name, "timer-mapzones")) { g_timerMapzones = true; - } + } else if (StrEqual(name, "timer-ljstats")) { g_timerLjStats = true; @@ -179,7 +179,7 @@ public OnLibraryAdded(const String:name[]) else if (StrEqual(name, "timer-rankings")) { g_timerRankings = true; - } + } else if (StrEqual(name, "timer-worldrecord")) { g_timerWorldRecord = true; @@ -187,45 +187,45 @@ public OnLibraryAdded(const String:name[]) } public OnLibraryRemoved(const String:name[]) -{ +{ if (StrEqual(name, "timer-physics")) { g_timerPhysics = false; - } + } else if (StrEqual(name, "timer-mapzones")) { g_timerMapzones = false; - } + } else if (StrEqual(name, "timer-ljstats")) { g_timerLjStats = false; - } + } else if (StrEqual(name, "timer-rankings")) { g_timerRankings = false; - } + } else if (StrEqual(name, "timer-worldrecord")) { g_timerWorldRecord = false; } } -public OnMapStart() +public OnMapStart() { for (new client = 1; client <= MaxClients; client++) { g_hDelayJump[client] = INVALID_HANDLE; } - + GetCurrentMap(g_currentMap, sizeof(g_currentMap)); - + if(GetEngineVersion() == Engine_CSGO) { CreateTimer(0.1, HUDTimer_CSGO, _, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT); } - + RestartMapTimer(); - + LoadPhysics(); LoadTimerSettings(); } @@ -254,7 +254,7 @@ public OnClientCookiesCached(client) // Initializations and preferences loading if(IsClientInGame(client) && !IsFakeClient(client)) { - loadClientCookiesFor(client); + loadClientCookiesFor(client); } } @@ -262,9 +262,9 @@ loadClientCookiesFor(client) { if(cookieHudPref == INVALID_HANDLE) return; - + decl String:buffer[5]; - + //Master HUD GetClientCookie(client, cookieHudPref, buffer, 5); if(!StrEqual(buffer, "")) @@ -278,14 +278,14 @@ loadClientCookiesFor(client) { hudSettings[Main][client] = StringToInt(buffer); } - + //Show Time? GetClientCookie(client, cookieHudMainTimePref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Time][client] = StringToInt(buffer); } - + //Show Jumps? GetClientCookie(client, cookieHudMainJumpsPref, buffer, 5); if(!StrEqual(buffer, "")) @@ -299,98 +299,98 @@ loadClientCookiesFor(client) { hudSettings[Speed][client] = StringToInt(buffer); } - + //Show SpeedMax? GetClientCookie(client, cookieHudMainSpeedMaxPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[SpeedMax][client] = StringToInt(buffer); } - + //Show JumpAcc? GetClientCookie(client, cookieHudMainJumpsAccPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[JumpAcc][client] = StringToInt(buffer); } - + //Show SideHUD? GetClientCookie(client, cookieHudSidePref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Side][client] = StringToInt(buffer); } - + //Show Side Map? GetClientCookie(client, cookieHudSideMapPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Map][client] = StringToInt(buffer); } - + //Show Side Mode? GetClientCookie(client, cookieHudSideModePref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Mode][client] = StringToInt(buffer); } - + //Show Side WR? GetClientCookie(client, cookieHudSideWRPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[WR][client] = StringToInt(buffer); } - + //Show Side Rank? GetClientCookie(client, cookieHudSideRankPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Rank][client] = StringToInt(buffer); } - + //Show Side PB? GetClientCookie(client, cookieHudSidePBPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[PB][client] = StringToInt(buffer); } - + //Show Side TTWR? GetClientCookie(client, cookieHudSideTTWRPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[TTWR][client] = StringToInt(buffer); } - + //Show Side Keys? GetClientCookie(client, cookieHudSideKeysPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Keys][client] = StringToInt(buffer); } - + //Show Side Spec? GetClientCookie(client, cookieHudSideSpecPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Spec][client] = StringToInt(buffer); } - + //Show Side Steam? GetClientCookie(client, cookieHudSideSteamPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Steam][client] = StringToInt(buffer); } - + //Show Side Level? GetClientCookie(client, cookieHudSideLevelPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Level][client] = StringToInt(buffer); } - + //Show Side Timeleft? GetClientCookie(client, cookieHudSideTimeleftPref, buffer, 5); if(!StrEqual(buffer, "")) @@ -419,330 +419,330 @@ public MenuHandlerHud(Handle:menu, MenuAction:action, client, itemNum) if (hudSettings[Master][client] == 0) { hudSettings[Master][client] = 1; - } - else if (hudSettings[Master][client] == 1) + } + else if (hudSettings[Master][client] == 1) { hudSettings[Master][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Master][client], buffer, 5); - SetClientCookie(client, cookieHudPref, buffer); + SetClientCookie(client, cookieHudPref, buffer); } - + if(StrEqual(info, "main")) { if (hudSettings[Main][client] == 0) { hudSettings[Main][client] = 1; - } - else if (hudSettings[Main][client] == 1) + } + else if (hudSettings[Main][client] == 1) { hudSettings[Main][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Main][client], buffer, 5); - SetClientCookie(client, cookieHudMainPref, buffer); + SetClientCookie(client, cookieHudMainPref, buffer); } - + if(StrEqual(info, "time")) { if (hudSettings[Time][client] == 0) { hudSettings[Time][client] = 1; - } - else if (hudSettings[Time][client] == 1) + } + else if (hudSettings[Time][client] == 1) { hudSettings[Time][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Time][client], buffer, 5); - SetClientCookie(client, cookieHudMainTimePref, buffer); + SetClientCookie(client, cookieHudMainTimePref, buffer); } - + if(StrEqual(info, "jumps")) { if (hudSettings[Jumps][client] == 0) { hudSettings[Jumps][client] = 1; - } - else if (hudSettings[Jumps][client] == 1) + } + else if (hudSettings[Jumps][client] == 1) { hudSettings[Jumps][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Jumps][client], buffer, 5); - SetClientCookie(client, cookieHudMainJumpsPref, buffer); + SetClientCookie(client, cookieHudMainJumpsPref, buffer); } - + if(StrEqual(info, "speed")) { if (hudSettings[Speed][client] == 0) { hudSettings[Speed][client] = 1; - } - else if (hudSettings[Speed][client] == 1) + } + else if (hudSettings[Speed][client] == 1) { hudSettings[Speed][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Speed][client], buffer, 5); - SetClientCookie(client, cookieHudMainSpeedPref, buffer); + SetClientCookie(client, cookieHudMainSpeedPref, buffer); } - + if(StrEqual(info, "speedmax")) { if (hudSettings[SpeedMax][client] == 0) { hudSettings[SpeedMax][client] = 1; - } - else if (hudSettings[SpeedMax][client] == 1) + } + else if (hudSettings[SpeedMax][client] == 1) { hudSettings[SpeedMax][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[SpeedMax][client], buffer, 5); - SetClientCookie(client, cookieHudMainSpeedMaxPref, buffer); + SetClientCookie(client, cookieHudMainSpeedMaxPref, buffer); } - + if(StrEqual(info, "jumpacc")) { if (hudSettings[JumpAcc][client] == 0) { hudSettings[JumpAcc][client] = 1; - } - else if (hudSettings[JumpAcc][client] == 1) + } + else if (hudSettings[JumpAcc][client] == 1) { hudSettings[JumpAcc][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[JumpAcc][client], buffer, 5); - SetClientCookie(client, cookieHudMainJumpsAccPref, buffer); + SetClientCookie(client, cookieHudMainJumpsAccPref, buffer); } - + if(StrEqual(info, "side")) { if (hudSettings[Side][client] == 0) { hudSettings[Side][client] = 1; - } - else if (hudSettings[Side][client] == 1) + } + else if (hudSettings[Side][client] == 1) { hudSettings[Side][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Side][client], buffer, 5); - SetClientCookie(client, cookieHudSidePref, buffer); + SetClientCookie(client, cookieHudSidePref, buffer); } - + if(StrEqual(info, "map")) { if (hudSettings[Map][client] == 0) { hudSettings[Map][client] = 1; - } - else if (hudSettings[Map][client] == 1) + } + else if (hudSettings[Map][client] == 1) { hudSettings[Map][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Map][client], buffer, 5); - SetClientCookie(client, cookieHudSideMapPref, buffer); + SetClientCookie(client, cookieHudSideMapPref, buffer); } - + if(StrEqual(info, "mode")) { if (hudSettings[Mode][client] == 0) { hudSettings[Mode][client] = 1; - } - else if (hudSettings[Mode][client] == 1) + } + else if (hudSettings[Mode][client] == 1) { hudSettings[Mode][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Mode][client], buffer, 5); - SetClientCookie(client, cookieHudSideModePref, buffer); + SetClientCookie(client, cookieHudSideModePref, buffer); } - + if(StrEqual(info, "wr")) { if (hudSettings[WR][client] == 0) { hudSettings[WR][client] = 1; - } - else if (hudSettings[WR][client] == 1) + } + else if (hudSettings[WR][client] == 1) { hudSettings[WR][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[WR][client], buffer, 5); - SetClientCookie(client, cookieHudSideWRPref, buffer); + SetClientCookie(client, cookieHudSideWRPref, buffer); } - + if(StrEqual(info, "level")) { if (hudSettings[Level][client] == 0) { hudSettings[Level][client] = 1; - } - else if (hudSettings[Level][client] == 1) + } + else if (hudSettings[Level][client] == 1) { hudSettings[Level][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Level][client], buffer, 5); - SetClientCookie(client, cookieHudSideLevelPref, buffer); + SetClientCookie(client, cookieHudSideLevelPref, buffer); } - + if(StrEqual(info, "timeleft")) { if (hudSettings[Timeleft][client] == 0) { hudSettings[Timeleft][client] = 1; - } - else if (hudSettings[Timeleft][client] == 1) + } + else if (hudSettings[Timeleft][client] == 1) { hudSettings[Timeleft][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Timeleft][client], buffer, 5); - SetClientCookie(client, cookieHudSideTimeleftPref, buffer); + SetClientCookie(client, cookieHudSideTimeleftPref, buffer); } - + if(StrEqual(info, "rank")) { if (hudSettings[Rank][client] == 0) { hudSettings[Rank][client] = 1; - } - else if (hudSettings[Rank][client] == 1) + } + else if (hudSettings[Rank][client] == 1) { hudSettings[Rank][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Rank][client], buffer, 5); - SetClientCookie(client, cookieHudSideRankPref, buffer); + SetClientCookie(client, cookieHudSideRankPref, buffer); } - + if(StrEqual(info, "pb")) { if (hudSettings[PB][client] == 0) { hudSettings[PB][client] = 1; - } - else if (hudSettings[PB][client] == 1) + } + else if (hudSettings[PB][client] == 1) { hudSettings[PB][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[PB][client], buffer, 5); - SetClientCookie(client, cookieHudSidePBPref, buffer); + SetClientCookie(client, cookieHudSidePBPref, buffer); } - + if(StrEqual(info, "ttwr")) { if (hudSettings[TTWR][client] == 0) { hudSettings[TTWR][client] = 1; - } - else if (hudSettings[TTWR][client] == 1) + } + else if (hudSettings[TTWR][client] == 1) { hudSettings[TTWR][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[TTWR][client], buffer, 5); - SetClientCookie(client, cookieHudSideTTWRPref, buffer); + SetClientCookie(client, cookieHudSideTTWRPref, buffer); } - + if(StrEqual(info, "keys")) { if (hudSettings[Keys][client] == 0) { hudSettings[Keys][client] = 1; - } - else if (hudSettings[Keys][client] == 1) + } + else if (hudSettings[Keys][client] == 1) { hudSettings[Keys][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Keys][client], buffer, 5); - SetClientCookie(client, cookieHudSideKeysPref, buffer); + SetClientCookie(client, cookieHudSideKeysPref, buffer); } - + if(StrEqual(info, "spec")) { if (hudSettings[Spec][client] == 0) { hudSettings[Spec][client] = 1; - } - else if (hudSettings[Spec][client] == 1) + } + else if (hudSettings[Spec][client] == 1) { hudSettings[Spec][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Spec][client], buffer, 5); - SetClientCookie(client, cookieHudSideSpecPref, buffer); + SetClientCookie(client, cookieHudSideSpecPref, buffer); } - + if(StrEqual(info, "steam")) { if (hudSettings[Steam][client] == 0) { hudSettings[Steam][client] = 1; - } - else if (hudSettings[Steam][client] == 1) + } + else if (hudSettings[Steam][client] == 1) { hudSettings[Steam][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Steam][client], buffer, 5); - SetClientCookie(client, cookieHudSideSteamPref, buffer); + SetClientCookie(client, cookieHudSideSteamPref, buffer); } - + if(StrEqual(info, "points")) { if (hudSettings[Points][client] == 0) { hudSettings[Points][client] = 1; - } - else if (hudSettings[Points][client] == 1) + } + else if (hudSettings[Points][client] == 1) { hudSettings[Points][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Points][client], buffer, 5); - SetClientCookie(client, cookieHudSidePointsPref, buffer); + SetClientCookie(client, cookieHudSidePointsPref, buffer); } } if(IsClientInGame(client)) ShowHudMenu(client, GetMenuSelectionPosition()); - } + } else if(action == MenuAction_End) { CloseHandle(menu); } - + } - + // This creates the Hud Menu public Action:MenuHud(client, args) { @@ -769,244 +769,244 @@ ShowHudMenu(client, start_item) { new Handle:menu = CreateMenu(MenuHandlerHud); decl String:buffer[100]; - + FormatEx(buffer, sizeof(buffer), "Custom Hud Menu"); SetMenuTitle(menu, buffer); - + if(hudSettings[Master][client] == 0) { - AddMenuItem(menu, "master", "Enable HUD Master Switch"); + AddMenuItem(menu, "master", "Enable HUD Master Switch"); } else { - AddMenuItem(menu, "master", "Disable HUD Master Switch"); + AddMenuItem(menu, "master", "Disable HUD Master Switch"); } - + if(g_Settings[HUDCenterEnable]) { if(hudSettings[Main][client] == 0) { - AddMenuItem(menu, "main", "Enable Center HUD"); + AddMenuItem(menu, "main", "Enable Center HUD"); } else { - AddMenuItem(menu, "main", "Disable Center HUD"); + AddMenuItem(menu, "main", "Disable Center HUD"); } } - + if(g_Settings[HUDSideEnable]) { if(hudSettings[Side][client] == 0) { - AddMenuItem(menu, "side", "Enable Side HUD"); + AddMenuItem(menu, "side", "Enable Side HUD"); } else { - AddMenuItem(menu, "side", "Disable Side HUD"); + AddMenuItem(menu, "side", "Disable Side HUD"); } } - + if(hudSettings[Time][client] == 0) { - AddMenuItem(menu, "time", "Enable Time"); + AddMenuItem(menu, "time", "Enable Time"); } else { - AddMenuItem(menu, "time", "Disable Time"); + AddMenuItem(menu, "time", "Disable Time"); } - + if(g_Settings[HUDJumpsEnable]) { if(hudSettings[Jumps][client] == 0) { - AddMenuItem(menu, "jumps", "Enable Jumps"); + AddMenuItem(menu, "jumps", "Enable Jumps"); } else { - AddMenuItem(menu, "jumps", "Disable Jumps"); + AddMenuItem(menu, "jumps", "Disable Jumps"); } } - + if(g_Settings[HUDSpeedEnable]) { if(hudSettings[Speed][client] == 0) { - AddMenuItem(menu, "speed", "Enable Speed"); + AddMenuItem(menu, "speed", "Enable Speed"); } else { - AddMenuItem(menu, "speed", "Disable Speed"); + AddMenuItem(menu, "speed", "Disable Speed"); } } - + if(g_Settings[HUDSpeedMaxEnable]) { if(hudSettings[SpeedMax][client] == 0) { - AddMenuItem(menu, "speedmax", "Enable Max Speed"); + AddMenuItem(menu, "speedmax", "Enable Max Speed"); } else { - AddMenuItem(menu, "speedmax", "Disable Max Speed"); + AddMenuItem(menu, "speedmax", "Disable Max Speed"); } } - + if(g_Settings[HUDJumpAccEnable]) { if(hudSettings[JumpAcc][client] == 0) { - AddMenuItem(menu, "jumpacc", "Enable Jump Accuracy"); + AddMenuItem(menu, "jumpacc", "Enable Jump Accuracy"); } else { - AddMenuItem(menu, "jumpacc", "Disable Jump Accuracy"); + AddMenuItem(menu, "jumpacc", "Disable Jump Accuracy"); } } - + if(g_Settings[HUDSpeclistEnable]) { if(hudSettings[Spec][client] == 0) { - AddMenuItem(menu, "spec", "Enable Spec List[SideHUD]"); + AddMenuItem(menu, "spec", "Enable Spec List[SideHUD]"); } else { - AddMenuItem(menu, "spec", "Disable Spec List[SideHUD]"); + AddMenuItem(menu, "spec", "Disable Spec List[SideHUD]"); } } - + if(g_Settings[HUDPointsEnable]) { if(hudSettings[Points][client] == 0) { - AddMenuItem(menu, "points", "Enable Points[SideHUD]"); + AddMenuItem(menu, "points", "Enable Points[SideHUD]"); } else { - AddMenuItem(menu, "points", "Disable Points[SideHUD]"); + AddMenuItem(menu, "points", "Disable Points[SideHUD]"); } } - + if(g_Settings[HUDMapEnable]) { if(hudSettings[Map][client] == 0) { - AddMenuItem(menu, "map", "Enable Map Display [SideHUD]"); + AddMenuItem(menu, "map", "Enable Map Display [SideHUD]"); } else { - AddMenuItem(menu, "map", "Disable Map Display [SideHUD]"); + AddMenuItem(menu, "map", "Disable Map Display [SideHUD]"); } } - + if(g_Settings[HUDStyleEnable]) { if(hudSettings[Mode][client] == 0) { - AddMenuItem(menu, "mode", "Enable Style Display [SideHUD]"); + AddMenuItem(menu, "mode", "Enable Style Display [SideHUD]"); } else { - AddMenuItem(menu, "mode", "Disable Style Display [SideHUD]"); + AddMenuItem(menu, "mode", "Disable Style Display [SideHUD]"); } } - + if(g_Settings[HUDWREnable]) { if(hudSettings[WR][client] == 0) { - AddMenuItem(menu, "wr", "Enable WR Display [SideHUD]"); + AddMenuItem(menu, "wr", "Enable WR Display [SideHUD]"); } else { - AddMenuItem(menu, "wr", "Disable WR Display [SideHUD]"); + AddMenuItem(menu, "wr", "Disable WR Display [SideHUD]"); } } - + if(g_Settings[HUDRankEnable]) { if(hudSettings[Rank][client] == 0) { - AddMenuItem(menu, "rank", "Enable Rank Display [SideHUD]"); + AddMenuItem(menu, "rank", "Enable Rank Display [SideHUD]"); } else { - AddMenuItem(menu, "rank", "Disable Rank Display [SideHUD]"); + AddMenuItem(menu, "rank", "Disable Rank Display [SideHUD]"); } } - + if(g_Settings[HUDLevelEnable]) { if(hudSettings[Level][client] == 0) { - AddMenuItem(menu, "level", "Enable Level Display [SideHUD]"); + AddMenuItem(menu, "level", "Enable Level Display [SideHUD]"); } else { - AddMenuItem(menu, "level", "Disable Level Display [SideHUD]"); + AddMenuItem(menu, "level", "Disable Level Display [SideHUD]"); } } - + if(g_Settings[HUDPBEnable]) { if(hudSettings[PB][client] == 0) { - AddMenuItem(menu, "pb", "Enable Personal Best [SideHUD]"); + AddMenuItem(menu, "pb", "Enable Personal Best [SideHUD]"); } else { - AddMenuItem(menu, "pb", "Disable Personal Best [SideHUD]"); + AddMenuItem(menu, "pb", "Disable Personal Best [SideHUD]"); } } - + if(g_Settings[HUDTTWREnable]) { if(hudSettings[TTWR][client] == 0) { - AddMenuItem(menu, "ttwr", "Enable TTWR Display [SideHUD]"); + AddMenuItem(menu, "ttwr", "Enable TTWR Display [SideHUD]"); } else { - AddMenuItem(menu, "ttwr", "Disable TTWR Display [SideHUD]"); + AddMenuItem(menu, "ttwr", "Disable TTWR Display [SideHUD]"); } } - + if(g_Settings[HUDTimeleftEnable]) { if(hudSettings[Timeleft][client] == 0) { - AddMenuItem(menu, "timeleft", "Enable Timeleft Display [SideHUD]"); + AddMenuItem(menu, "timeleft", "Enable Timeleft Display [SideHUD]"); } else { - AddMenuItem(menu, "timeleft", "Disable Timeleft Display [SideHUD]"); + AddMenuItem(menu, "timeleft", "Disable Timeleft Display [SideHUD]"); } } - + if(g_Settings[HUDKeysEnable]) { if(hudSettings[Keys][client] == 0) { - AddMenuItem(menu, "keys", "Enable Keys Display [SideHUD/Spec only]"); + AddMenuItem(menu, "keys", "Enable Keys Display [SideHUD/Spec only]"); } else { - AddMenuItem(menu, "keys", "Disable Keys Display [SideHUD/Spec only]"); + AddMenuItem(menu, "keys", "Disable Keys Display [SideHUD/Spec only]"); } } - + if(g_Settings[HUDSteamIDEnable]) { if(hudSettings[Steam][client] == 0) { - AddMenuItem(menu, "steam", "Enable Steam [SideHUD/Spec only]"); + AddMenuItem(menu, "steam", "Enable Steam [SideHUD/Spec only]"); } else { - AddMenuItem(menu, "steam", "Disable Steam [SideHUD/Spec only]"); + AddMenuItem(menu, "steam", "Disable Steam [SideHUD/Spec only]"); } } - + SetMenuExitButton(menu, true); DisplayMenuAtItem(menu, client, start_item, MENU_TIME_FOREVER ); @@ -1030,7 +1030,7 @@ public Action:Cmd_HideMyAss(client, args) PrintToChat(client, "Hide My Ass: Enabled."); } } - return Plugin_Handled; + return Plugin_Handled; } public OnConfigsExecuted() @@ -1051,9 +1051,9 @@ stock RestartMapTimer() CloseHandle(g_hThink_Map); g_hThink_Map = INVALID_HANDLE; } - + new bool:gotTimeLeft = GetMapTimeLeft(g_iMap_TimeLeft); - + if(gotTimeLeft && g_iMap_TimeLeft > 0) { g_hThink_Map = CreateTimer(THINK_INTERVAL, Timer_Think_Map, INVALID_HANDLE, TIMER_REPEAT); @@ -1091,13 +1091,13 @@ public OnClientPutInServer(client) hudSettings[Steam][client] = 1; hudSettings[Points][client] = 1; hudSettings[Timeleft][client] = 1; - + if (AreClientCookiesCached(client)) { loadClientCookiesFor(client); } } - + if(g_hThink_Map == INVALID_HANDLE && IsServerProcessing()) { RestartMapTimer(); @@ -1115,7 +1115,7 @@ public Action:Event_PlayerJump(Handle:event, const String:name[], bool:dontBroad g_iJumps[client]++; g_hDelayJump[client] = CreateTimer(0.3, Timer_DelayJumpHud, client, TIMER_FLAG_NO_MAPCHANGE); - + return Plugin_Continue; } @@ -1129,9 +1129,9 @@ public Action:Timer_DelayJumpHud(Handle:timer, any:client) public Action:Event_Reset(Handle:event, const String:name[], bool:dontBroadcast) { new client = GetClientOfUserId(GetEventInt(event, "userid")); - + g_iJumps[client] = 0; - + if (g_hDelayJump[client] != INVALID_HANDLE) { CloseHandle(g_hDelayJump[client]); @@ -1146,15 +1146,15 @@ public Action:HUDTimer_CSGO(Handle:timer) { spec[client] = false; } - + for (new client = 1; client <= MaxClients; client++) { if (!IsClientInGame(client)) continue; - + if(hidemyass[client]) continue; - + // Get target he's spectating if(!IsPlayerAlive(client) || IsClientObserver(client)) { @@ -1169,7 +1169,7 @@ public Action:HUDTimer_CSGO(Handle:timer) } } } - + for (new client = 1; client <= MaxClients; client++) { if (IsClientInGame(client)) @@ -1185,23 +1185,23 @@ UpdateHUD_CSGO(client) { return; } - + if(!hudSettings[Master][client]) { return; } - + if(!g_Settings[HUDMasterEnable]) { return; } - + new iClientToShow, iObserverMode; //new iButtons; // Show own buttons by default iClientToShow = client; - + // Get target he's spectating if(!IsPlayerAlive(client) || IsClientObserver(client)) { @@ -1209,7 +1209,7 @@ UpdateHUD_CSGO(client) if(iObserverMode == SPECMODE_FIRSTPERSON || iObserverMode == SPECMODE_3RDPERSON) { iClientToShow = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - + // Check client index if(iClientToShow <= 0 || iClientToShow > MaxClients) return; @@ -1219,15 +1219,15 @@ UpdateHUD_CSGO(client) return; // don't proceed, if in freelook.. } } - + if(g_timerLjStats && IsClientInLJMode(iClientToShow)) { return; } - + //start building HUD - new String:centerText[512]; //HUD buffer - + new String:centerText[512]; //HUD buffer + //collect player info decl String:auth[32]; //steam ID if(!IsFakeClient(iClientToShow)) @@ -1248,34 +1248,30 @@ UpdateHUD_CSGO(client) new bestJumps; //best round jumps new jumps; //current jump count new fpsmax; //fps settings - new bool:bonus = false; //track timer running + new track; //track timer running new Float:time; //current time new RecordId; new Float:RecordTime; new RankTotal; - + if(g_timerWorldRecord) Timer_GetClientTimer(iClientToShow, enabled, time, jumps, fpsmax); - - new style; - if(g_timerPhysics) style = Timer_GetStyle(iClientToShow); + + new style; + if(g_timerPhysics) style = Timer_GetStyle(iClientToShow); new ranked; if(g_timerPhysics) ranked = Timer_IsStyleRanked(style); - + //get current player level new currentLevel = 0; if(g_timerMapzones) currentLevel = Timer_GetClientLevelID(iClientToShow); if(currentLevel < 1) currentLevel = 1; - - //bonuslevel? - if(currentLevel > 1000) - { - bonus = true; - } - + + track = Timer_GetTrack(iClientToShow); + //get bhop mode - if (g_timerPhysics) + if (g_timerPhysics) { - Timer_GetStyleRecordWRStats(style, bonus, RecordId, RecordTime, RankTotal); + Timer_GetStyleRecordWRStats(style, track, RecordId, RecordTime, RankTotal); //correct fail format Timer_SecondsToTime(time, buffer, sizeof(buffer), 0); } @@ -1292,25 +1288,25 @@ UpdateHUD_CSGO(client) //get jump accuracy new Float:accuracy = 0.0; if(g_timerPhysics) Timer_GetJumpAccuracy(iClientToShow, accuracy); - + if(accuracy > 100.0) accuracy = 100.0; else if(accuracy < 0.0) accuracy = 0.0; - - if(ranked) + + if(ranked) { - if(g_timerWorldRecord) Timer_GetBestRound(iClientToShow, style, bonus, bestTime, bestJumps); + if(g_timerWorldRecord) Timer_GetBestRound(iClientToShow, style, track, bestTime, bestJumps); Timer_SecondsToTime(bestTime, bestbuffer, sizeof(bestbuffer), 2); } - + //has client a mate? //new mate = 0; //challenge mode //if (g_timerMapzones) mate = Timer_GetClientTeammate(iClientToShow); - + new points; if(g_timerRankings) points = Timer_GetPoints(iClientToShow); new points100 = points; if(g_Settings[HUDUseMVPStars] > 0) points100 = RoundToFloor((points*1.0)/g_Settings[HUDUseMVPStars]); - + //Update Stats if(client == iClientToShow) { @@ -1319,25 +1315,25 @@ UpdateHUD_CSGO(client) //SetEntProp(client, Prop_Data, "m_iFrags", currentLevel); //SetEntProp(client, Prop_Data, "m_iFrags", Timer_GetPoints(client)); } - + new rank; - - if(ranked && g_timerWorldRecord) + + if(ranked && g_timerWorldRecord) { //get rank - rank = Timer_GetStyleRank(iClientToShow, bonus, style); + rank = Timer_GetStyleRank(iClientToShow, track, style); } - + new prank; if(g_timerRankings) prank = Timer_GetPointRank(iClientToShow); - + if(prank > 2000 || prank < 1) prank = 2000; - + new nprank = (prank * -1); - + new String:sRankTotal[32]; Format(sRankTotal, sizeof(sRankTotal), "%d", RankTotal); - + if(client == iClientToShow) { if(g_Settings[HUDUseMVPStars] > 0 && points100 > 0) @@ -1352,7 +1348,7 @@ UpdateHUD_CSGO(client) { Client_SetDeaths(client, rank); } - + if(g_Settings[HUDUseClanTag] && !IsFakeClient(client)) { decl String:tagbuffer[32]; @@ -1361,10 +1357,10 @@ UpdateHUD_CSGO(client) if(enabled) FormatEx(tagbuffer, sizeof(tagbuffer), "%s", buffer); else if (ranked) FormatEx(tagbuffer, sizeof(tagbuffer), "%s", bestbuffer); } - + if(g_Settings[HUDUseClanTagTime] && g_Settings[MultimodeEnable] && g_Settings[HUDUseClanTagStyle]) Format(tagbuffer, sizeof(tagbuffer), " %s", tagbuffer); - + if(g_Settings[MultimodeEnable] && g_Settings[HUDUseClanTagStyle]) { if(!enabled && !ranked) @@ -1376,41 +1372,57 @@ UpdateHUD_CSGO(client) Format(tagbuffer, sizeof(tagbuffer), "%s%s", g_Physics[style][StyleTagShortName], tagbuffer); } } - + CS_SetClientClanTag(client, tagbuffer); } } - + //start format center HUD - + new stagecount; - - if(g_timerMapzones) + + if(g_timerMapzones) { - if(bonus) + if(track == TRACK_BONUS) { stagecount = Timer_GetMapzoneCount(ZtBonusLevel)+Timer_GetMapzoneCount(ZtBonusCheckpoint)+1; } + else if(track == TRACK_BONUS2) + { + stagecount = Timer_GetMapzoneCount(ZtBonus2Level)+Timer_GetMapzoneCount(ZtBonus2Checkpoint)+1; + } + else if(track == TRACK_BONUS3) + { + stagecount = Timer_GetMapzoneCount(ZtBonus3Level)+Timer_GetMapzoneCount(ZtBonus3Checkpoint)+1; + } + else if(track == TRACK_BONUS4) + { + stagecount = Timer_GetMapzoneCount(ZtBonus4Level)+Timer_GetMapzoneCount(ZtBonus4Checkpoint)+1; + } + else if(track == TRACK_BONUS5) + { + stagecount = Timer_GetMapzoneCount(ZtBonus5Level)+Timer_GetMapzoneCount(ZtBonus5Checkpoint)+1; + } else { stagecount = Timer_GetMapzoneCount(ZtLevel)+Timer_GetMapzoneCount(ZtCheckpoint)+1; } } - + if(currentLevel > 1000) currentLevel -= 1000; if(currentLevel == 999) currentLevel = stagecount; - + /* Time: 00:01 [Stage 3/4] Record: 01:55:41 [Rank: 3/4] Speed: 455.23 [Style: Auto] */ - + decl String:timeString[64]; Timer_SecondsToTime(time, timeString, sizeof(timeString), 1); - + if(StrEqual(timeString, "00:-0.0")) Format(timeString, sizeof(timeString), "00:00.0"); - + //First Line if (hudSettings[Level][client] && g_Settings[MultimodeEnable]) { @@ -1422,11 +1434,11 @@ UpdateHUD_CSGO(client) { Format(centerText, sizeof(centerText), "%sStage: %d/%d", centerText, currentLevel, stagecount); } - + if(hudSettings[Time][client]) Format(centerText, sizeof(centerText), "%s | ", centerText); } - - if(hudSettings[Time][client]) + + if(hudSettings[Time][client]) { if(Timer_GetPauseStatus(iClientToShow)) { @@ -1456,10 +1468,10 @@ UpdateHUD_CSGO(client) { Format(centerText, sizeof(centerText), "%s%t: %d", centerText, "Jumps", jumps); } - + if(hudSettings[Time][client] || hudSettings[Level][client] || hudSettings[Jumps][client]) Format(centerText, sizeof(centerText), "%s\n", centerText); - + if(ranked && g_timerWorldRecord) { //Secound Line @@ -1469,23 +1481,23 @@ UpdateHUD_CSGO(client) Format(centerText, sizeof(centerText), "%sRank: -/%s", centerText, sRankTotal); else Format(centerText, sizeof(centerText), "%sRank: %d/%s", centerText, rank, sRankTotal); - + if(hudSettings[PB][client]) Format(centerText, sizeof(centerText), "%s | ", centerText); } - - if(hudSettings[PB][client]) + + if(hudSettings[PB][client]) { - Timer_GetBestRound(iClientToShow, style, bonus, bestTime, bestJumps); + Timer_GetBestRound(iClientToShow, style, track, bestTime, bestJumps); Timer_SecondsToTime(bestTime, bestbuffer, sizeof(bestbuffer), 2); - + Format(centerText, sizeof(centerText), "%sRecord: %s", centerText, bestbuffer); } - + if(hudSettings[PB][client] || hudSettings[Rank][client]) Format(centerText, sizeof(centerText), "%s\n", centerText); } else Format(centerText, sizeof(centerText), "%sUnranked (Fun Style)\n", centerText); - + //Third Line if (hudSettings[Mode][client] && g_Settings[MultimodeEnable]) { @@ -1502,19 +1514,19 @@ UpdateHUD_CSGO(client) { Format(centerText, sizeof(centerText), "%sStage: %d/%d", centerText, currentLevel, stagecount); } - + if(hudSettings[Speed][client]) Format(centerText, sizeof(centerText), "%s | ", centerText); } - - if(hudSettings[Speed][client]) + + if(hudSettings[Speed][client]) Format(centerText, sizeof(centerText), "%sSpeed: %5.2f", centerText, currentspeed); - + //if(hudSettings[Speed][client] || hudSettings[Mode][client]) //Format(centerText, sizeof(centerText), "%s\n", centerText); - + if (g_Settings[HUDCenterEnable] && hudSettings[Main][client]) { - if(!IsVoteInProgress()) + if(!IsVoteInProgress()) { PrintHintText(client, centerText); } @@ -1540,34 +1552,34 @@ public Action:Cmd_SpecInfo(client, args) { Print_Specinfo(client, owner); } - - return Plugin_Handled; + + return Plugin_Handled; } Print_Specinfo(client, owner) { new String:buffer[1024]; - + new spec_count = GetSpecCount(client); new count = 0; - - for(new j = 1; j <= MaxClients; j++) + + for(new j = 1; j <= MaxClients; j++) { if (!IsClientInGame(j) || !IsClientObserver(j)) continue; - + if (IsClientSourceTV(j)) continue; - + new iSpecMode = GetEntProp(j, Prop_Send, "m_iObserverMode"); - + // The client isn't spectating any one person, so ignore them. if (iSpecMode != SPECMODE_FIRSTPERSON && iSpecMode != SPECMODE_3RDPERSON) continue; - + // Find out who the client is spectating. new iTarget = GetEntPropEnt(j, Prop_Send, "m_hObserverTarget"); - + // Are they spectating the same player as User? if (iTarget == client && j != client && !hidemyass[j]) { @@ -1576,43 +1588,43 @@ Print_Specinfo(client, owner) { Format(buffer, sizeof(buffer), "%s %N", buffer, j); } - else + else { Format(buffer, sizeof(buffer), "%s %N,", buffer, j); } } } - + CPrintToChat(owner, "%s {red}%N {olive}has {red}%d {olive}spectators:{red}%s.", PLUGIN_PREFIX2, client, count, buffer); } stock GetSpecCount(client) { new count = 0; - - for(new j = 1; j <= MaxClients; j++) + + for(new j = 1; j <= MaxClients; j++) { if (!IsClientInGame(j) || !IsClientObserver(j)) continue; - + if (IsClientSourceTV(j)) continue; - + new iSpecMode = GetEntProp(j, Prop_Send, "m_iObserverMode"); - + // The client isn't spectating any one person, so ignore them. if (iSpecMode != SPECMODE_FIRSTPERSON && iSpecMode != SPECMODE_3RDPERSON) continue; - + // Find out who the client is spectating. new iTarget = GetEntPropEnt(j, Prop_Send, "m_hObserverTarget"); - + // Are they spectating the same player as User? if (iTarget == client && j != client && !hidemyass[j]) { count++; } } - + return count; } diff --git a/gameserver/addons/sourcemod/scripting/timer-hud_css.sp b/gameserver/addons/sourcemod/scripting/timer-hud_css.sp index 2e1a319..2ca928f 100644 --- a/gameserver/addons/sourcemod/scripting/timer-hud_css.sp +++ b/gameserver/addons/sourcemod/scripting/timer-hud_css.sp @@ -117,7 +117,7 @@ public OnPluginStart() SetFailState("Check timer error logs."); return; } - + g_timerCore = LibraryExists("timer"); g_timerPhysics = LibraryExists("timer-physics"); g_timerMapzones = LibraryExists("timer-mapzones"); @@ -126,31 +126,31 @@ public OnPluginStart() g_timerRankings = LibraryExists("timer-rankings"); g_timerStrafes = LibraryExists("timer-strafes"); g_timerWorldRecord = LibraryExists("timer-worldrecord"); - + LoadPhysics(); LoadTimerSettings(); - + LoadTranslations("timer.phrases"); - - if(g_Settings[HUDMasterEnable]) + + if(g_Settings[HUDMasterEnable]) { HookEvent("player_jump", Event_PlayerJump); - + HookEvent("player_death", Event_Reset); HookEvent("player_team", Event_Reset); HookEvent("player_spawn", Event_Reset); HookEvent("player_disconnect", Event_Reset); - + RegConsoleCmd("sm_hidemyass", Cmd_HideMyAss); RegConsoleCmd("sm_hud", MenuHud); RegConsoleCmd("sm_hudmenu", MenuHud); RegConsoleCmd("sm_hudstyle", MenuHud); RegConsoleCmd("sm_specinfo", Cmd_SpecInfo); - + g_cvarTimeLimit = FindConVar("mp_timelimit"); - + AutoExecConfig(true, "timer/timer-hud"); - + //cookies yummy :) cookieHudPref = RegClientCookie("timer_hud_master", "Turn on or off all hud components", CookieAccess_Private); cookieHudMainPref = RegClientCookie("timer_hud_main", "Turn on or off main hud components", CookieAccess_Private); @@ -182,31 +182,31 @@ public OnLibraryAdded(const String:name[]) if (StrEqual(name, "timer")) { g_timerCore = true; - } + } else if (StrEqual(name, "timer-physics")) { g_timerPhysics = true; - } + } else if (StrEqual(name, "timer-mapzones")) { g_timerMapzones = true; - } + } else if (StrEqual(name, "timer-ljstats")) { g_timerLjStats = true; - } + } else if (StrEqual(name, "timer-maptier")) { g_timerMapTier = true; - } + } else if (StrEqual(name, "timer-rankings")) { g_timerRankings = true; - } + } else if (StrEqual(name, "timer-strafes")) { g_timerStrafes = true; - } + } else if (StrEqual(name, "timer-worldrecord")) { g_timerWorldRecord = true; @@ -214,57 +214,57 @@ public OnLibraryAdded(const String:name[]) } public OnLibraryRemoved(const String:name[]) -{ +{ if (StrEqual(name, "timer")) { g_timerCore = false; - } + } else if (StrEqual(name, "timer-physics")) { g_timerPhysics = false; - } + } else if (StrEqual(name, "timer-mapzones")) { g_timerMapzones = false; - } + } else if (StrEqual(name, "timer-ljstats")) { g_timerLjStats = false; - } + } else if (StrEqual(name, "timer-maptier")) { g_timerMapTier = false; - } + } else if (StrEqual(name, "timer-rankings")) { g_timerRankings = false; - } + } else if (StrEqual(name, "timer-strafes")) { g_timerStrafes = false; - } + } else if (StrEqual(name, "timer-worldrecord")) { g_timerWorldRecord = false; } } -public OnMapStart() +public OnMapStart() { for (new client = 1; client <= MaxClients; client++) { g_hDelayJump[client] = INVALID_HANDLE; } - + GetCurrentMap(g_currentMap, sizeof(g_currentMap)); - + if(GetEngineVersion() == Engine_CSS) { CreateTimer(0.1, HUDTimer_CSS, _, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT); } - + RestartMapTimer(); - + LoadPhysics(); LoadTimerSettings(); } @@ -293,7 +293,7 @@ public OnClientCookiesCached(client) // Initializations and preferences loading if(IsClientInGame(client) && !IsFakeClient(client)) { - loadClientCookiesFor(client); + loadClientCookiesFor(client); } } @@ -301,9 +301,9 @@ loadClientCookiesFor(client) { if(cookieHudPref == INVALID_HANDLE) return; - + decl String:buffer[5]; - + //Master HUD GetClientCookie(client, cookieHudPref, buffer, 5); if(!StrEqual(buffer, "")) @@ -317,14 +317,14 @@ loadClientCookiesFor(client) { hudSettings[Main][client] = StringToInt(buffer); } - + //Show Time? GetClientCookie(client, cookieHudMainTimePref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Time][client] = StringToInt(buffer); } - + //Show Jumps? GetClientCookie(client, cookieHudMainJumpsPref, buffer, 5); if(!StrEqual(buffer, "")) @@ -338,112 +338,112 @@ loadClientCookiesFor(client) { hudSettings[Speed][client] = StringToInt(buffer); } - + //Show SpeedMax? GetClientCookie(client, cookieHudMainSpeedMaxPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[SpeedMax][client] = StringToInt(buffer); } - + //Show Strafes? GetClientCookie(client, cookieHudMainStrafesPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Strafes][client] = StringToInt(buffer); } - + //Show JumpAcc? GetClientCookie(client, cookieHudMainJumpsAccPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[JumpAcc][client] = StringToInt(buffer); } - + //Show SideHUD? GetClientCookie(client, cookieHudSidePref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Side][client] = StringToInt(buffer); } - + //Show Side Map? GetClientCookie(client, cookieHudSideMapPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Map][client] = StringToInt(buffer); } - + //Show Side Mode? GetClientCookie(client, cookieHudSideModePref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Mode][client] = StringToInt(buffer); } - + //Show Side WR Holder? GetClientCookie(client, cookieHudSideWRHolderPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[WRHolder][client] = StringToInt(buffer); } - + //Show Side WR? GetClientCookie(client, cookieHudSideWRPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[WR][client] = StringToInt(buffer); } - + //Show Side Rank? GetClientCookie(client, cookieHudSideRankPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Rank][client] = StringToInt(buffer); } - + //Show Side PB? GetClientCookie(client, cookieHudSidePBPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[PB][client] = StringToInt(buffer); } - + //Show Side TTWR? GetClientCookie(client, cookieHudSideTTWRPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[TTWR][client] = StringToInt(buffer); } - + //Show Side Keys? GetClientCookie(client, cookieHudSideKeysPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Keys][client] = StringToInt(buffer); } - + //Show Side Spec? GetClientCookie(client, cookieHudSideSpecPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Spec][client] = StringToInt(buffer); } - + //Show Side Steam? GetClientCookie(client, cookieHudSideSteamPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Steam][client] = StringToInt(buffer); } - + //Show Side Level? GetClientCookie(client, cookieHudSideLevelPref, buffer, 5); if(!StrEqual(buffer, "")) { hudSettings[Level][client] = StringToInt(buffer); } - + //Show Side Timeleft? GetClientCookie(client, cookieHudSideTimeleftPref, buffer, 5); if(!StrEqual(buffer, "")) @@ -472,362 +472,362 @@ public MenuHandlerHud(Handle:menu, MenuAction:action, client, itemNum) if (hudSettings[Master][client] == 0) { hudSettings[Master][client] = 1; - } - else if (hudSettings[Master][client] == 1) + } + else if (hudSettings[Master][client] == 1) { hudSettings[Master][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Master][client], buffer, 5); - SetClientCookie(client, cookieHudPref, buffer); + SetClientCookie(client, cookieHudPref, buffer); } - + if(StrEqual(info, "main")) { if (hudSettings[Main][client] == 0) { hudSettings[Main][client] = 1; - } - else if (hudSettings[Main][client] == 1) + } + else if (hudSettings[Main][client] == 1) { hudSettings[Main][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Main][client], buffer, 5); - SetClientCookie(client, cookieHudMainPref, buffer); + SetClientCookie(client, cookieHudMainPref, buffer); } - + if(StrEqual(info, "time")) { if (hudSettings[Time][client] == 0) { hudSettings[Time][client] = 1; - } - else if (hudSettings[Time][client] == 1) + } + else if (hudSettings[Time][client] == 1) { hudSettings[Time][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Time][client], buffer, 5); - SetClientCookie(client, cookieHudMainTimePref, buffer); + SetClientCookie(client, cookieHudMainTimePref, buffer); } - + if(StrEqual(info, "jumps")) { if (hudSettings[Jumps][client] == 0) { hudSettings[Jumps][client] = 1; - } - else if (hudSettings[Jumps][client] == 1) + } + else if (hudSettings[Jumps][client] == 1) { hudSettings[Jumps][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Jumps][client], buffer, 5); - SetClientCookie(client, cookieHudMainJumpsPref, buffer); + SetClientCookie(client, cookieHudMainJumpsPref, buffer); } - + if(StrEqual(info, "speed")) { if (hudSettings[Speed][client] == 0) { hudSettings[Speed][client] = 1; - } - else if (hudSettings[Speed][client] == 1) + } + else if (hudSettings[Speed][client] == 1) { hudSettings[Speed][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Speed][client], buffer, 5); - SetClientCookie(client, cookieHudMainSpeedPref, buffer); + SetClientCookie(client, cookieHudMainSpeedPref, buffer); } - + if(StrEqual(info, "speedmax")) { if (hudSettings[SpeedMax][client] == 0) { hudSettings[SpeedMax][client] = 1; - } - else if (hudSettings[SpeedMax][client] == 1) + } + else if (hudSettings[SpeedMax][client] == 1) { hudSettings[SpeedMax][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[SpeedMax][client], buffer, 5); - SetClientCookie(client, cookieHudMainSpeedMaxPref, buffer); + SetClientCookie(client, cookieHudMainSpeedMaxPref, buffer); } - + if(StrEqual(info, "strafes")) { if (hudSettings[Strafes][client] == 0) { hudSettings[Strafes][client] = 1; - } - else if (hudSettings[Strafes][client] == 1) + } + else if (hudSettings[Strafes][client] == 1) { hudSettings[Strafes][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Strafes][client], buffer, 5); - SetClientCookie(client, cookieHudMainStrafesPref, buffer); + SetClientCookie(client, cookieHudMainStrafesPref, buffer); } - + if(StrEqual(info, "jumpacc")) { if (hudSettings[JumpAcc][client] == 0) { hudSettings[JumpAcc][client] = 1; - } - else if (hudSettings[JumpAcc][client] == 1) + } + else if (hudSettings[JumpAcc][client] == 1) { hudSettings[JumpAcc][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[JumpAcc][client], buffer, 5); - SetClientCookie(client, cookieHudMainJumpsAccPref, buffer); + SetClientCookie(client, cookieHudMainJumpsAccPref, buffer); } - + if(StrEqual(info, "side")) { if (hudSettings[Side][client] == 0) { hudSettings[Side][client] = 1; - } - else if (hudSettings[Side][client] == 1) + } + else if (hudSettings[Side][client] == 1) { hudSettings[Side][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Side][client], buffer, 5); - SetClientCookie(client, cookieHudSidePref, buffer); + SetClientCookie(client, cookieHudSidePref, buffer); } - + if(StrEqual(info, "map")) { if (hudSettings[Map][client] == 0) { hudSettings[Map][client] = 1; - } - else if (hudSettings[Map][client] == 1) + } + else if (hudSettings[Map][client] == 1) { hudSettings[Map][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Map][client], buffer, 5); - SetClientCookie(client, cookieHudSideMapPref, buffer); + SetClientCookie(client, cookieHudSideMapPref, buffer); } - + if(StrEqual(info, "mode")) { if (hudSettings[Mode][client] == 0) { hudSettings[Mode][client] = 1; - } - else if (hudSettings[Mode][client] == 1) + } + else if (hudSettings[Mode][client] == 1) { hudSettings[Mode][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Mode][client], buffer, 5); - SetClientCookie(client, cookieHudSideModePref, buffer); + SetClientCookie(client, cookieHudSideModePref, buffer); } - + if(StrEqual(info, "wrholder")) { if (hudSettings[WRHolder][client] == 0) { hudSettings[WRHolder][client] = 1; - } - else if (hudSettings[WRHolder][client] == 1) + } + else if (hudSettings[WRHolder][client] == 1) { hudSettings[WRHolder][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[WRHolder][client], buffer, 5); - SetClientCookie(client, cookieHudSideWRHolderPref, buffer); + SetClientCookie(client, cookieHudSideWRHolderPref, buffer); } - + if(StrEqual(info, "wr")) { if (hudSettings[WR][client] == 0) { hudSettings[WR][client] = 1; - } - else if (hudSettings[WR][client] == 1) + } + else if (hudSettings[WR][client] == 1) { hudSettings[WR][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[WR][client], buffer, 5); - SetClientCookie(client, cookieHudSideWRPref, buffer); + SetClientCookie(client, cookieHudSideWRPref, buffer); } - + if(StrEqual(info, "level")) { if (hudSettings[Level][client] == 0) { hudSettings[Level][client] = 1; - } - else if (hudSettings[Level][client] == 1) + } + else if (hudSettings[Level][client] == 1) { hudSettings[Level][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Level][client], buffer, 5); - SetClientCookie(client, cookieHudSideLevelPref, buffer); + SetClientCookie(client, cookieHudSideLevelPref, buffer); } - + if(StrEqual(info, "timeleft")) { if (hudSettings[Timeleft][client] == 0) { hudSettings[Timeleft][client] = 1; - } - else if (hudSettings[Timeleft][client] == 1) + } + else if (hudSettings[Timeleft][client] == 1) { hudSettings[Timeleft][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Timeleft][client], buffer, 5); - SetClientCookie(client, cookieHudSideTimeleftPref, buffer); + SetClientCookie(client, cookieHudSideTimeleftPref, buffer); } - + if(StrEqual(info, "rank")) { if (hudSettings[Rank][client] == 0) { hudSettings[Rank][client] = 1; - } - else if (hudSettings[Rank][client] == 1) + } + else if (hudSettings[Rank][client] == 1) { hudSettings[Rank][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Rank][client], buffer, 5); - SetClientCookie(client, cookieHudSideRankPref, buffer); + SetClientCookie(client, cookieHudSideRankPref, buffer); } - + if(StrEqual(info, "pb")) { if (hudSettings[PB][client] == 0) { hudSettings[PB][client] = 1; - } - else if (hudSettings[PB][client] == 1) + } + else if (hudSettings[PB][client] == 1) { hudSettings[PB][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[PB][client], buffer, 5); - SetClientCookie(client, cookieHudSidePBPref, buffer); + SetClientCookie(client, cookieHudSidePBPref, buffer); } - + if(StrEqual(info, "ttwr")) { if (hudSettings[TTWR][client] == 0) { hudSettings[TTWR][client] = 1; - } - else if (hudSettings[TTWR][client] == 1) + } + else if (hudSettings[TTWR][client] == 1) { hudSettings[TTWR][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[TTWR][client], buffer, 5); - SetClientCookie(client, cookieHudSideTTWRPref, buffer); + SetClientCookie(client, cookieHudSideTTWRPref, buffer); } - + if(StrEqual(info, "keys")) { if (hudSettings[Keys][client] == 0) { hudSettings[Keys][client] = 1; - } - else if (hudSettings[Keys][client] == 1) + } + else if (hudSettings[Keys][client] == 1) { hudSettings[Keys][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Keys][client], buffer, 5); - SetClientCookie(client, cookieHudSideKeysPref, buffer); + SetClientCookie(client, cookieHudSideKeysPref, buffer); } - + if(StrEqual(info, "spec")) { if (hudSettings[Spec][client] == 0) { hudSettings[Spec][client] = 1; - } - else if (hudSettings[Spec][client] == 1) + } + else if (hudSettings[Spec][client] == 1) { hudSettings[Spec][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Spec][client], buffer, 5); - SetClientCookie(client, cookieHudSideSpecPref, buffer); + SetClientCookie(client, cookieHudSideSpecPref, buffer); } - + if(StrEqual(info, "steam")) { if (hudSettings[Steam][client] == 0) { hudSettings[Steam][client] = 1; - } - else if (hudSettings[Steam][client] == 1) + } + else if (hudSettings[Steam][client] == 1) { hudSettings[Steam][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Steam][client], buffer, 5); - SetClientCookie(client, cookieHudSideSteamPref, buffer); + SetClientCookie(client, cookieHudSideSteamPref, buffer); } - + if(StrEqual(info, "points")) { if (hudSettings[Points][client] == 0) { hudSettings[Points][client] = 1; - } - else if (hudSettings[Points][client] == 1) + } + else if (hudSettings[Points][client] == 1) { hudSettings[Points][client] = 0; } - + decl String:buffer[5]; IntToString(hudSettings[Points][client], buffer, 5); - SetClientCookie(client, cookieHudSidePointsPref, buffer); + SetClientCookie(client, cookieHudSidePointsPref, buffer); } } if(IsClientInGame(client)) ShowHudMenu(client, GetMenuSelectionPosition()); - } + } else if(action == MenuAction_End) { CloseHandle(menu); } - + } - + // This creates the Hud Menu public Action:MenuHud(client, args) { @@ -854,268 +854,268 @@ ShowHudMenu(client, start_item) { new Handle:menu = CreateMenu(MenuHandlerHud); decl String:buffer[100]; - + FormatEx(buffer, sizeof(buffer), "Custom Hud Menu"); SetMenuTitle(menu, buffer); - + if(hudSettings[Master][client] == 0) { - AddMenuItem(menu, "master", "Enable HUD Master Switch"); + AddMenuItem(menu, "master", "Enable HUD Master Switch"); } else { - AddMenuItem(menu, "master", "Disable HUD Master Switch"); + AddMenuItem(menu, "master", "Disable HUD Master Switch"); } - + if(g_Settings[HUDCenterEnable]) { if(hudSettings[Main][client] == 0) { - AddMenuItem(menu, "main", "Enable Center HUD"); + AddMenuItem(menu, "main", "Enable Center HUD"); } else { - AddMenuItem(menu, "main", "Disable Center HUD"); + AddMenuItem(menu, "main", "Disable Center HUD"); } } - + if(g_Settings[HUDSideEnable]) { if(hudSettings[Side][client] == 0) { - AddMenuItem(menu, "side", "Enable Side HUD"); + AddMenuItem(menu, "side", "Enable Side HUD"); } else { - AddMenuItem(menu, "side", "Disable Side HUD"); + AddMenuItem(menu, "side", "Disable Side HUD"); } } - + if(hudSettings[Time][client] == 0) { - AddMenuItem(menu, "time", "Enable Time"); + AddMenuItem(menu, "time", "Enable Time"); } else { - AddMenuItem(menu, "time", "Disable Time"); + AddMenuItem(menu, "time", "Disable Time"); } - + if(g_Settings[HUDJumpsEnable]) { if(hudSettings[Jumps][client] == 0) { - AddMenuItem(menu, "jumps", "Enable Jumps"); + AddMenuItem(menu, "jumps", "Enable Jumps"); } else { - AddMenuItem(menu, "jumps", "Disable Jumps"); + AddMenuItem(menu, "jumps", "Disable Jumps"); } } - + if(g_Settings[HUDSpeedEnable]) { if(hudSettings[Speed][client] == 0) { - AddMenuItem(menu, "speed", "Enable Speed"); + AddMenuItem(menu, "speed", "Enable Speed"); } else { - AddMenuItem(menu, "speed", "Disable Speed"); + AddMenuItem(menu, "speed", "Disable Speed"); } } - + if(g_Settings[HUDSpeedMaxEnable]) { if(hudSettings[SpeedMax][client] == 0) { - AddMenuItem(menu, "speedmax", "Enable Max Speed"); + AddMenuItem(menu, "speedmax", "Enable Max Speed"); } else { - AddMenuItem(menu, "speedmax", "Disable Max Speed"); + AddMenuItem(menu, "speedmax", "Disable Max Speed"); } } - + if(g_Settings[HUDStrafesEnable]) { if(hudSettings[Strafes][client] == 0) { - AddMenuItem(menu, "strafes", "Enable Strafe Counter"); + AddMenuItem(menu, "strafes", "Enable Strafe Counter"); } else { - AddMenuItem(menu, "strafes", "Disable Strafe Counter"); + AddMenuItem(menu, "strafes", "Disable Strafe Counter"); } } - + if(g_Settings[HUDJumpAccEnable]) { if(hudSettings[JumpAcc][client] == 0) { - AddMenuItem(menu, "jumpacc", "Enable Jump Accuracy"); + AddMenuItem(menu, "jumpacc", "Enable Jump Accuracy"); } else { - AddMenuItem(menu, "jumpacc", "Disable Jump Accuracy"); + AddMenuItem(menu, "jumpacc", "Disable Jump Accuracy"); } } - + if(g_Settings[HUDSpeclistEnable]) { if(hudSettings[Spec][client] == 0) { - AddMenuItem(menu, "spec", "Enable Spec List[SideHUD]"); + AddMenuItem(menu, "spec", "Enable Spec List[SideHUD]"); } else { - AddMenuItem(menu, "spec", "Disable Spec List[SideHUD]"); + AddMenuItem(menu, "spec", "Disable Spec List[SideHUD]"); } } - + if(g_Settings[HUDPointsEnable]) { if(hudSettings[Points][client] == 0) { - AddMenuItem(menu, "points", "Enable Points[SideHUD]"); + AddMenuItem(menu, "points", "Enable Points[SideHUD]"); } else { - AddMenuItem(menu, "points", "Disable Points[SideHUD]"); + AddMenuItem(menu, "points", "Disable Points[SideHUD]"); } } - + if(g_Settings[HUDMapEnable]) { if(hudSettings[Map][client] == 0) { - AddMenuItem(menu, "map", "Enable Map Display [SideHUD]"); + AddMenuItem(menu, "map", "Enable Map Display [SideHUD]"); } else { - AddMenuItem(menu, "map", "Disable Map Display [SideHUD]"); + AddMenuItem(menu, "map", "Disable Map Display [SideHUD]"); } } - + if(g_Settings[HUDStyleEnable]) { if(hudSettings[Mode][client] == 0) { - AddMenuItem(menu, "mode", "Enable Style Display [SideHUD]"); + AddMenuItem(menu, "mode", "Enable Style Display [SideHUD]"); } else { - AddMenuItem(menu, "mode", "Disable Style Display [SideHUD]"); + AddMenuItem(menu, "mode", "Disable Style Display [SideHUD]"); } } - + if(g_Settings[HUDWREnable]) { if(hudSettings[WR][client] == 0) { - AddMenuItem(menu, "wrholder", "Enable WR Holder Display [SideHUD]"); + AddMenuItem(menu, "wrholder", "Enable WR Holder Display [SideHUD]"); } else { - AddMenuItem(menu, "wrholder", "Disable WR Holder Display [SideHUD]"); + AddMenuItem(menu, "wrholder", "Disable WR Holder Display [SideHUD]"); } } - + if(g_Settings[HUDWREnable]) { if(hudSettings[WR][client] == 0) { - AddMenuItem(menu, "wr", "Enable WR Time Display [SideHUD]"); + AddMenuItem(menu, "wr", "Enable WR Time Display [SideHUD]"); } else { - AddMenuItem(menu, "wr", "Disable WR Time Display [SideHUD]"); + AddMenuItem(menu, "wr", "Disable WR Time Display [SideHUD]"); } } - + if(g_Settings[HUDRankEnable]) { if(hudSettings[Rank][client] == 0) { - AddMenuItem(menu, "rank", "Enable Rank Display [SideHUD]"); + AddMenuItem(menu, "rank", "Enable Rank Display [SideHUD]"); } else { - AddMenuItem(menu, "rank", "Disable Rank Display [SideHUD]"); + AddMenuItem(menu, "rank", "Disable Rank Display [SideHUD]"); } } - + if(g_Settings[HUDLevelEnable]) { if(hudSettings[Level][client] == 0) { - AddMenuItem(menu, "level", "Enable Level Display [SideHUD]"); + AddMenuItem(menu, "level", "Enable Level Display [SideHUD]"); } else { - AddMenuItem(menu, "level", "Disable Level Display [SideHUD]"); + AddMenuItem(menu, "level", "Disable Level Display [SideHUD]"); } } - + if(g_Settings[HUDPBEnable]) { if(hudSettings[PB][client] == 0) { - AddMenuItem(menu, "pb", "Enable Personal Best [SideHUD]"); + AddMenuItem(menu, "pb", "Enable Personal Best [SideHUD]"); } else { - AddMenuItem(menu, "pb", "Disable Personal Best [SideHUD]"); + AddMenuItem(menu, "pb", "Disable Personal Best [SideHUD]"); } } - + if(g_Settings[HUDTTWREnable]) { if(hudSettings[TTWR][client] == 0) { - AddMenuItem(menu, "ttwr", "Enable TTWR Display [SideHUD]"); + AddMenuItem(menu, "ttwr", "Enable TTWR Display [SideHUD]"); } else { - AddMenuItem(menu, "ttwr", "Disable TTWR Display [SideHUD]"); + AddMenuItem(menu, "ttwr", "Disable TTWR Display [SideHUD]"); } } - + if(g_Settings[HUDTimeleftEnable]) { if(hudSettings[Timeleft][client] == 0) { - AddMenuItem(menu, "timeleft", "Enable Timeleft Display [SideHUD]"); + AddMenuItem(menu, "timeleft", "Enable Timeleft Display [SideHUD]"); } else { - AddMenuItem(menu, "timeleft", "Disable Timeleft Display [SideHUD]"); + AddMenuItem(menu, "timeleft", "Disable Timeleft Display [SideHUD]"); } } - + if(g_Settings[HUDKeysEnable]) { if(hudSettings[Keys][client] == 0) { - AddMenuItem(menu, "keys", "Enable Keys Display [SideHUD/Spec only]"); + AddMenuItem(menu, "keys", "Enable Keys Display [SideHUD/Spec only]"); } else { - AddMenuItem(menu, "keys", "Disable Keys Display [SideHUD/Spec only]"); + AddMenuItem(menu, "keys", "Disable Keys Display [SideHUD/Spec only]"); } } - + if(g_Settings[HUDSteamIDEnable]) { if(hudSettings[Steam][client] == 0) { - AddMenuItem(menu, "steam", "Enable Steam [SideHUD/Spec only]"); + AddMenuItem(menu, "steam", "Enable Steam [SideHUD/Spec only]"); } else { - AddMenuItem(menu, "steam", "Disable Steam [SideHUD/Spec only]"); + AddMenuItem(menu, "steam", "Disable Steam [SideHUD/Spec only]"); } } - + SetMenuExitButton(menu, true); DisplayMenuAtItem(menu, client, start_item, MENU_TIME_FOREVER ); @@ -1139,7 +1139,7 @@ public Action:Cmd_HideMyAss(client, args) PrintToChat(client, "Hide My Ass: Enabled."); } } - return Plugin_Handled; + return Plugin_Handled; } public OnConfigsExecuted() @@ -1160,9 +1160,9 @@ stock RestartMapTimer() CloseHandle(g_hThink_Map); g_hThink_Map = INVALID_HANDLE; } - + new bool:gotTimeLeft = GetMapTimeLeft(g_iMap_TimeLeft); - + if(gotTimeLeft && g_iMap_TimeLeft > 0) { g_hThink_Map = CreateTimer(THINK_INTERVAL, Timer_Think_Map, INVALID_HANDLE, TIMER_REPEAT); @@ -1202,13 +1202,13 @@ public OnClientPutInServer(client) hudSettings[Steam][client] = 1; hudSettings[Points][client] = 1; hudSettings[Timeleft][client] = 1; - + if (AreClientCookiesCached(client)) { loadClientCookiesFor(client); } } - + if(g_hThink_Map == INVALID_HANDLE && IsServerProcessing()) { RestartMapTimer(); @@ -1226,7 +1226,7 @@ public Action:Event_PlayerJump(Handle:event, const String:name[], bool:dontBroad g_iJumps[client]++; g_hDelayJump[client] = CreateTimer(0.3, Timer_DelayJumpHud, client, TIMER_FLAG_NO_MAPCHANGE); - + return Plugin_Continue; } @@ -1240,9 +1240,9 @@ public Action:Timer_DelayJumpHud(Handle:timer, any:client) public Action:Event_Reset(Handle:event, const String:name[], bool:dontBroadcast) { new client = GetClientOfUserId(GetEventInt(event, "userid")); - + g_iJumps[client] = 0; - + if (g_hDelayJump[client] != INVALID_HANDLE) { CloseHandle(g_hDelayJump[client]); @@ -1257,15 +1257,15 @@ public Action:HUDTimer_CSS(Handle:timer) { spec[client] = false; } - + for (new client = 1; client <= MaxClients; client++) { if (!IsClientInGame(client)) continue; - + if(hidemyass[client]) continue; - + // Get target he's spectating if(!IsPlayerAlive(client) || IsClientObserver(client)) { @@ -1280,7 +1280,7 @@ public Action:HUDTimer_CSS(Handle:timer) } } } - + for (new client = 1; client <= MaxClients; client++) { if (IsClientInGame(client)) @@ -1294,21 +1294,21 @@ UpdateHUD_CSS(client) { if(!g_timerCore) return; - + if(!IsClientInGame(client)) return; - + if(!hudSettings[Master][client]) return; - + if(!g_Settings[HUDMasterEnable]) return; - + new iClientToShow, iButtons, iObserverMode; // Show own buttons by default iClientToShow = client; - + // Get target he's spectating if(!IsPlayerAlive(client) || IsClientObserver(client)) { @@ -1316,7 +1316,7 @@ UpdateHUD_CSS(client) if(iObserverMode == SPECMODE_FIRSTPERSON || iObserverMode == SPECMODE_3RDPERSON) { iClientToShow = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - + // Check client index if(iClientToShow <= 0 || iClientToShow > MaxClients) return; @@ -1326,21 +1326,28 @@ UpdateHUD_CSS(client) return; // don't proceed, if in freelook.. } } - + if(g_timerLjStats && IsClientInLJMode(iClientToShow)) { return; } - + //start building HUD - new String:hintText[512]; //HUD buffer - new String:centerText[512]; //HUD buffer - + new String:hintText[512]; //HUD buffer + new String:centerText[512]; //HUD buffer + //collect player info decl String:auth[32]; //steam ID - if(!IsFakeClient(iClientToShow)) GetClientAuthString(iClientToShow, auth, sizeof(auth)); + if(!IsFakeClient(iClientToShow)) + { + #if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7 + GetClientAuthId(iClientToShow, AuthId_Steam2, auth, sizeof(auth)); + #else + GetClientAuthString(iClientToShow, auth, sizeof(auth)); + #endif + } else FormatEx(auth, sizeof(auth), "Replay-Bot"); - + iButtons = g_iButtonsPressed[iClientToShow]; //buttons pressed //collect player stats @@ -1351,45 +1358,40 @@ UpdateHUD_CSS(client) new bestJumps; //best round jumps new jumps; //current jump count new fpsmax; //fps settings - new bool:bonus = false; //bonus timer running + new track; //bonus timer running new Float:time; //current time new RecordId; new Float:RecordTime; new RankTotal; new String:WrName[32]; - + Timer_GetClientTimer(iClientToShow, enabled, time, jumps, fpsmax); - - new style, ranked; - if(g_timerPhysics) + + new style, ranked; + if(g_timerPhysics) { - style = Timer_GetStyle(iClientToShow); + style = Timer_GetStyle(iClientToShow); ranked = Timer_IsStyleRanked(style); } - + //get current player level new currentLevel = 0; if(g_timerMapzones) currentLevel = Timer_GetClientLevelID(iClientToShow); if(currentLevel < 1) currentLevel = 1; - - //bonuslevel? - if(currentLevel > 1000) - { - currentLevel -= 1000; - bonus = true; - } - + + track = Timer_GetTrack(iClientToShow); + //get bhop mode - if (g_timerPhysics && g_timerWorldRecord) + if (g_timerPhysics && g_timerWorldRecord) { - Timer_GetStyleRecordWRStats(style, bonus, RecordId, RecordTime, RankTotal); + Timer_GetStyleRecordWRStats(style, track, RecordId, RecordTime, RankTotal); Timer_SecondsToTime(time, buffer, sizeof(buffer), 0); - Timer_GetRecordHolderName(style, bonus, 1, WrName, 32); + Timer_GetRecordHolderName(style, track, 1, WrName, 32); } - + //get maptier new tier = 1; - if(g_timerMapTier) tier = Timer_GetTier(bonus); + if(g_timerMapTier) tier = Timer_GetTier(track); //get speed new Float:maxspeed; @@ -1398,7 +1400,7 @@ UpdateHUD_CSS(client) if(g_timerPhysics) Timer_GetCurrentSpeed(iClientToShow, currentspeed); new Float:avgspeed; if(g_timerPhysics) Timer_GetAvgSpeed(iClientToShow, avgspeed); - + if(g_Settings[HUDSpeedUnit] == 1) { maxspeed *= 0.06858; @@ -1409,43 +1411,43 @@ UpdateHUD_CSS(client) //get jump accuracy new Float:accuracy = 0.0; if(g_timerPhysics) Timer_GetJumpAccuracy(iClientToShow, accuracy); - + if(accuracy > 100.0) accuracy = 100.0; else if(accuracy < 0.0) accuracy = 0.0; - - if(ranked) + + if(ranked) { - if(g_timerWorldRecord) Timer_GetBestRound(iClientToShow, style, bonus, bestTime, bestJumps); + if(g_timerWorldRecord) Timer_GetBestRound(iClientToShow, style, track, bestTime, bestJumps); Timer_SecondsToTime(bestTime, bestbuffer, sizeof(bestbuffer), 2); } - + //has client a mate? new mate = 0; //challenge mode if (g_timerMapzones) mate = Timer_GetClientTeammate(iClientToShow); - + new points; if(g_timerRankings) points = Timer_GetPoints(iClientToShow); new points100 = points; if(g_Settings[HUDUseMVPStars] > 0) points100 = RoundToFloor((points*1.0)/g_Settings[HUDUseMVPStars]); new rank; - - if(ranked && g_timerWorldRecord) + + if(ranked && g_timerWorldRecord) { //get rank - rank = Timer_GetStyleRank(iClientToShow, bonus, style); + rank = Timer_GetStyleRank(iClientToShow, track, style); } - + new prank; if(g_timerRankings) prank = Timer_GetPointRank(iClientToShow); - + if(prank > 2000 || prank < 1) prank = 2000; - + new nprank = (prank * -1); - + new String:sRankTotal[32]; Format(sRankTotal, sizeof(sRankTotal), "%d", RankTotal); - + if(client == iClientToShow) { if(g_Settings[HUDUseMVPStars] > 0 && points100 > 0) @@ -1460,7 +1462,7 @@ UpdateHUD_CSS(client) { Client_SetDeaths(client, rank); } - + if(g_Settings[HUDUseClanTag] && !IsFakeClient(client)) { decl String:tagbuffer[32]; @@ -1469,10 +1471,10 @@ UpdateHUD_CSS(client) if(enabled) FormatEx(tagbuffer, sizeof(tagbuffer), "%s", buffer); else if (ranked) FormatEx(tagbuffer, sizeof(tagbuffer), "%s", bestbuffer); } - + if(g_Settings[HUDUseClanTagTime] && g_Settings[MultimodeEnable] && g_Settings[HUDUseClanTagStyle]) Format(tagbuffer, sizeof(tagbuffer), " %s", tagbuffer); - + if(g_Settings[MultimodeEnable] && g_Settings[HUDUseClanTagStyle]) { if(!enabled && !ranked) @@ -1484,44 +1486,60 @@ UpdateHUD_CSS(client) Format(tagbuffer, sizeof(tagbuffer), "%s%s", g_Physics[style][StyleTagShortName], tagbuffer); } } - + CS_SetClientClanTag(client, tagbuffer); } } - + //start format center HUD - + new stagecount; - + if(g_timerMapzones) { - if(bonus) + if(track == TRACK_BONUS) { stagecount = Timer_GetMapzoneCount(ZtBonusLevel)+Timer_GetMapzoneCount(ZtBonusCheckpoint)+1; } + else if(track == TRACK_BONUS2) + { + stagecount = Timer_GetMapzoneCount(ZtBonus2Level)+Timer_GetMapzoneCount(ZtBonus2Checkpoint)+1; + } + else if(track == TRACK_BONUS3) + { + stagecount = Timer_GetMapzoneCount(ZtBonus3Level)+Timer_GetMapzoneCount(ZtBonus3Checkpoint)+1; + } + else if(track == TRACK_BONUS4) + { + stagecount = Timer_GetMapzoneCount(ZtBonus4Level)+Timer_GetMapzoneCount(ZtBonus4Checkpoint)+1; + } + else if(track == TRACK_BONUS5) + { + stagecount = Timer_GetMapzoneCount(ZtBonus5Level)+Timer_GetMapzoneCount(ZtBonus5Checkpoint)+1; + } else { stagecount = Timer_GetMapzoneCount(ZtLevel)+Timer_GetMapzoneCount(ZtCheckpoint)+1; } } - + if (enabled) { decl String:timeString[64]; Timer_SecondsToTime(time, timeString, sizeof(timeString), 1); - + if(StrEqual(timeString, "00:-0.0")) FormatEx(timeString, sizeof(timeString), "00:00.0"); - + if (hudSettings[Time][client]) Format(centerText, sizeof(centerText), "%sTime: %s\n", centerText, timeString); //Format(centerText, sizeof(centerText), "%s%t: %s\n", centerText, "Time", timeString); - + if ((hudSettings[Jumps][client] && g_Settings[HUDJumpsEnable]) && (hudSettings[JumpAcc][client] && g_Settings[HUDJumpAccEnable]) && !g_Physics[style][StyleAuto]) Format(centerText, sizeof(centerText), "%s%t: %d [%.2f %%]\n", centerText, "Jumps", jumps, accuracy); else if (hudSettings[Jumps][client] && g_Settings[HUDJumpsEnable]) Format(centerText, sizeof(centerText), "%s%t: %d\n", centerText, "Jumps", jumps); } - + if(!enabled) { if (hudSettings[Speed][client] && g_Settings[HUDSpeedEnable]) @@ -1529,13 +1547,13 @@ UpdateHUD_CSS(client) Format(centerText, sizeof(centerText), "%s%t: %d%s", centerText, "HUD Speed", RoundToFloor(currentspeed), g_Settings[HUDSpeedUnit] == 1 ? "km/h" : ""); } } - else + else { if(g_timerStrafes && hudSettings[Strafes][client] && g_Settings[HUDStrafesEnable]) { Format(centerText, sizeof(centerText), "%sStrafes: %d\n", centerText, Timer_GetStrafeCount(iClientToShow)); } - + if(hudSettings[Speed][client] && g_Settings[HUDSpeedEnable]) { if(hudSettings[SpeedMax][client] && g_Settings[HUDSpeedMaxEnable]) @@ -1548,7 +1566,7 @@ UpdateHUD_CSS(client) } } } - + if (g_Settings[HUDCenterEnable] && hudSettings[Main][client]) { if(!IsVoteInProgress()) @@ -1560,41 +1578,41 @@ UpdateHUD_CSS(client) else PrintHintText(client, centerText); } } - + //PrintCenterText(client, centerText); - + //start format side HUD - - + + if (iClientToShow != client && (iObserverMode == SPECMODE_FIRSTPERSON || iObserverMode == SPECMODE_3RDPERSON)) { //Format(hintText, sizeof(hintText), "%sName: %s%N\n", hintText, client_tag, iClientToShow); if (hudSettings[Steam][client] && g_Settings[HUDSteamIDEnable]) Format(hintText, sizeof(hintText), "%sSteamID: %s\n", hintText, auth); } - + if (hudSettings[Points][client] && g_Settings[HUDPointsEnable]) Format(hintText, sizeof(hintText), "%sPoints: %d\n", hintText, points); - + if(0 < mate && IsClientInGame(mate)) { Format(hintText, sizeof(hintText), "%sTeammate: %N\n", hintText, mate); } - + //Format(hintText, sizeof(hintText), "%s %s - %t: %d/5\n", hintText, "Tier", g_currentMap, tier); if (hudSettings[Map][client] && g_Settings[HUDMapEnable]) Format(hintText, sizeof(hintText), "%s%s (Tier %d)\n", hintText, g_currentMap, tier); - + new String:RecordTimeString[32]; new String:DiffTimeString[32]; new bool:negate = false; - + if(ranked) { - + Timer_SecondsToTime(RecordTime, RecordTimeString, sizeof(RecordTimeString), 2); - + if(time-RecordTime >= 0) { Timer_SecondsToTime(time-RecordTime, DiffTimeString, sizeof(DiffTimeString), 2); @@ -1604,37 +1622,37 @@ UpdateHUD_CSS(client) negate = true; Timer_SecondsToTime(RecordTime-time, DiffTimeString, sizeof(DiffTimeString), 2); } - - + + //correct fail format if(StrEqual(RecordTimeString, "00:-0.00")) FormatEx(RecordTimeString, sizeof(RecordTimeString), "00:00.00"); if(StrEqual(RecordTimeString, "00:00.-0")) FormatEx(RecordTimeString, sizeof(RecordTimeString), "00:00.00"); } - - if (g_timerPhysics && g_Settings[MultimodeEnable]) - { + + if (g_timerPhysics && g_Settings[MultimodeEnable]) + { if (hudSettings[Mode][client] && g_Settings[HUDStyleEnable]) Format(hintText, sizeof(hintText), "%sStyle: %s\n", hintText, g_Physics[style][StyleName]); } - + if(ranked && RecordTime > 0.0) { if (hudSettings[WRHolder][client] && g_Settings[HUDWRHolderEnable]) Format(hintText, sizeof(hintText), "%sWR Holder: %s\n", hintText, WrName); - + if (hudSettings[WR][client] && g_Settings[HUDWREnable]) Format(hintText, sizeof(hintText), "%sWR Time: %s\n", hintText, RecordTimeString); - + if (hudSettings[WR][client] || hudSettings[Mode][client] || hudSettings[Map][client]) Format(hintText, sizeof(hintText), "%s\n", hintText); //Format(hintText, sizeof(hintText), "%s\n%N:\n", hintText, iClientToShow); } - + if (hudSettings[Level][client] && g_Settings[HUDLevelEnable]) { if(stagecount <= 1) { - if(bonus) + if(track > TRACK_NORMAL) { Format(hintText, sizeof(hintText), "%sBonus-Stage: Linear\n", hintText); } @@ -1643,12 +1661,22 @@ UpdateHUD_CSS(client) Format(hintText, sizeof(hintText), "%sStage: Linear\n", hintText); } } - else if(bonus) + else if(track > TRACK_NORMAL) { - if(currentLevel == 999) - Format(hintText, sizeof(hintText), "%sBonus-Stage: End/%d\n", hintText, stagecount); + if(track > TRACK_BONUS) + { + if(currentLevel == 999) + Format(hintText, sizeof(hintText), "%sBonus%d-Stage: End/%d\n", hintText, track, stagecount); + else + Format(hintText, sizeof(hintText), "%sBonus%d-Stage: %d/%d\n", hintText, track, currentLevel, stagecount); + } else - Format(hintText, sizeof(hintText), "%sBonus-Stage: %d/%d\n", hintText, currentLevel, stagecount); + { + if(currentLevel == 999) + Format(hintText, sizeof(hintText), "%sBonus-Stage: End/%d\n", hintText, stagecount); + else + Format(hintText, sizeof(hintText), "%sBonus-Stage: %d/%d\n", hintText, currentLevel, stagecount); + } } else { @@ -1658,7 +1686,7 @@ UpdateHUD_CSS(client) Format(hintText, sizeof(hintText), "%sStage: %d/%d\n", hintText, currentLevel, stagecount); } } - + if(ranked) { if (hudSettings[Rank][client] && g_Settings[HUDRankEnable]) @@ -1668,10 +1696,10 @@ UpdateHUD_CSS(client) else Format(hintText, sizeof(hintText), "%sRank: %d/%s\n", hintText, rank, sRankTotal); } - + if (hudSettings[PB][client] && g_Settings[HUDPBEnable]) Format(hintText, sizeof(hintText), "%sBest Time: %s\n", hintText, bestbuffer, bestJumps); - + if (hudSettings[TTWR][client] && g_Settings[HUDTTWREnable]) { if(RecordTime > 0 && time > 0) @@ -1684,8 +1712,8 @@ UpdateHUD_CSS(client) else Format(hintText, sizeof(hintText), "%sTime2WR: 00:00.00\n", hintText); } } - - if(hudSettings[Timeleft][client] && g_Settings[HUDTimeleftEnable]) + + if(hudSettings[Timeleft][client] && g_Settings[HUDTimeleftEnable]) { if(g_iMap_TimeLeft > 0) { @@ -1693,49 +1721,49 @@ UpdateHUD_CSS(client) } else Format(hintText,sizeof(hintText),"%sTimeleft: %d:%02d\n", hintText, (RoundToFloor(g_iMap_TimeLeft*-1.0))/60, (RoundToFloor(g_iMap_TimeLeft*-1.0))%60); } - + //speclist if (hudSettings[Spec][client] && g_Settings[HUDSpeclistEnable]) { new iSpecCount; - - for(new j = 1; j <= MaxClients; j++) + + for(new j = 1; j <= MaxClients; j++) { if (!IsClientInGame(j) || !IsClientObserver(j)) continue; - + if (IsClientSourceTV(j)) continue; - + new iSpecMode = GetEntProp(j, Prop_Send, "m_iObserverMode"); - + // The client isn't spectating any one person, so ignore them. if (iSpecMode != SPECMODE_FIRSTPERSON && iSpecMode != SPECMODE_3RDPERSON) continue; - + // Find out who the client is spectating. new iTarget = GetEntPropEnt(j, Prop_Send, "m_hObserverTarget"); - + // Are they spectating the same player as User? if (iTarget == iClientToShow && j != iClientToShow && !hidemyass[j]) iSpecCount++; } - + if(iSpecCount > 0) { Format(hintText, sizeof(hintText), "%sSpectators: %d\n\n", hintText, iSpecCount); } } - + if (hudSettings[Keys][client] && g_Settings[HUDKeysEnable]) { //if client is spectating show player keys if (iClientToShow != client && (iObserverMode == SPECMODE_FIRSTPERSON || iObserverMode == SPECMODE_3RDPERSON)) { Format(hintText, sizeof(hintText), "%s_______Keys_______\n\n", hintText); - + //dealing with keys pressed - + // Is he pressing "w"? if(iButtons & IN_FORWARD) Format(hintText, sizeof(hintText), "%sW;", hintText); @@ -1754,42 +1782,42 @@ UpdateHUD_CSS(client) // Is he pressing "+right"? if(iButtons & IN_RIGHT) Format(hintText, sizeof(hintText), "%s+R;", hintText); - + // Is he pressing "space"? if(iButtons & IN_JUMP || g_hDelayJump[iClientToShow] != INVALID_HANDLE) Format(hintText, sizeof(hintText), "%sJP;", hintText); - + // Is he pressing "ctrl"? if(iButtons & IN_DUCK) Format(hintText, sizeof(hintText), "%sDK;", hintText); - + // Is he pressing "shift"? if(iButtons & IN_SPEED) Format(hintText, sizeof(hintText), "%sWALK;", hintText); - + // Is he pressing "e"? if(iButtons & IN_USE) Format(hintText, sizeof(hintText), "%sU;", hintText); - + // Is he pressing "mouse1"? if(iButtons & IN_ATTACK) Format(hintText, sizeof(hintText), "%sM1;", hintText); - + // Is he pressing "mouse1"? if(iButtons & IN_ATTACK2) Format(hintText, sizeof(hintText), "%sM2;", hintText); - + // Is he pressing "tab"? if(iButtons & IN_SCORE) Format(hintText, sizeof(hintText), "%sTAB;", hintText); } - + //if player has a mate show keys pressed by players mate - + if(0 < mate && IsClientInGame(mate)) { new mbuttons = g_iButtonsPressed[mate]; - + Format(hintText, sizeof(hintText), "%s\n____Keys-Mate_____\n\n", hintText); // Is he pressing "w"? @@ -1810,43 +1838,43 @@ UpdateHUD_CSS(client) // Is he pressing "+right"? if(mbuttons & IN_RIGHT) Format(hintText, sizeof(hintText), "%s+R;", hintText); - + // Is he pressing "space"? if(mbuttons & IN_JUMP || g_hDelayJump[mate] != INVALID_HANDLE) Format(hintText, sizeof(hintText), "%sJP;", hintText); - + // Is he pressing "ctrl"? if(mbuttons & IN_DUCK) Format(hintText, sizeof(hintText), "%sDK;", hintText); - + // Is he pressing "shift"? if(mbuttons & IN_SPEED) Format(hintText, sizeof(hintText), "%sWALK;", hintText); - + // Is he pressing "e"? if(mbuttons & IN_USE) Format(hintText, sizeof(hintText), "%sU;", hintText); - + // Is he pressing "tab"? if(mbuttons & IN_SCORE) Format(hintText, sizeof(hintText), "%sTAB;", hintText); - + // Is he pressing "mouse1"? if(mbuttons & IN_ATTACK) Format(hintText, sizeof(hintText), "%sM1;", hintText); - + // Is he pressing "mouse1"? if(mbuttons & IN_ATTACK2) Format(hintText, sizeof(hintText), "%sM2;", hintText); } } - + //Print as his Text if (hudSettings[Side][client] && g_Settings[HUDSideEnable]) { Client_PrintKeyHintText(client, hintText); } - + //stop confusing hint sound StopSound(client, SNDCHAN_STATIC, "UI/hint.wav"); } @@ -1870,34 +1898,34 @@ public Action:Cmd_SpecInfo(client, args) { Print_Specinfo(client, owner); } - - return Plugin_Handled; + + return Plugin_Handled; } Print_Specinfo(client, owner) { new String:buffer[1024]; - + new spec_count = GetSpecCount(client); new count = 0; - - for(new j = 1; j <= MaxClients; j++) + + for(new j = 1; j <= MaxClients; j++) { if (!IsClientInGame(j) || !IsClientObserver(j)) continue; - + if (IsClientSourceTV(j)) continue; - + new iSpecMode = GetEntProp(j, Prop_Send, "m_iObserverMode"); - + // The client isn't spectating any one person, so ignore them. if (iSpecMode != SPECMODE_FIRSTPERSON && iSpecMode != SPECMODE_3RDPERSON) continue; - + // Find out who the client is spectating. new iTarget = GetEntPropEnt(j, Prop_Send, "m_hObserverTarget"); - + // Are they spectating the same player as User? if (iTarget == client && j != client && !hidemyass[j]) { @@ -1906,43 +1934,43 @@ Print_Specinfo(client, owner) { Format(buffer, sizeof(buffer), "%s %N", buffer, j); } - else + else { Format(buffer, sizeof(buffer), "%s %N,", buffer, j); } } } - + CPrintToChat(owner, "%s {red}%N {olive}has {red}%d {olive}spectators:{red}%s.", PLUGIN_PREFIX2, client, count, buffer); } stock GetSpecCount(client) { new count = 0; - - for(new j = 1; j <= MaxClients; j++) + + for(new j = 1; j <= MaxClients; j++) { if (!IsClientInGame(j) || !IsClientObserver(j)) continue; - + if (IsClientSourceTV(j)) continue; - + new iSpecMode = GetEntProp(j, Prop_Send, "m_iObserverMode"); - + // The client isn't spectating any one person, so ignore them. if (iSpecMode != SPECMODE_FIRSTPERSON && iSpecMode != SPECMODE_3RDPERSON) continue; - + // Find out who the client is spectating. new iTarget = GetEntPropEnt(j, Prop_Send, "m_hObserverTarget"); - + // Are they spectating the same player as User? if (iTarget == client && j != client && !hidemyass[j]) { count++; } } - + return count; -} \ No newline at end of file +} diff --git a/gameserver/addons/sourcemod/scripting/timer-ljstats.sp b/gameserver/addons/sourcemod/scripting/timer-ljstats.sp index a6161d8..4d06688 100644 --- a/gameserver/addons/sourcemod/scripting/timer-ljstats.sp +++ b/gameserver/addons/sourcemod/scripting/timer-ljstats.sp @@ -1827,7 +1827,11 @@ RecordQuery(client, JumpType:type, Float:distance, Float:pre, strafe) decl String:query[512], String:steamid[64], String:temp[64], String:name[64]; GetClientName(client, temp, sizeof(temp)); SQL_EscapeString(maindb, temp, name, sizeof(name)); - GetClientAuthString(client, steamid, sizeof(steamid)); + #if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7 + GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid)); + #else + GetClientAuthString(client, steamid, sizeof(steamid)); + #endif Format(query, sizeof(query), "select distance from 'ljstats' where steamid = '%s' and type = %d", steamid, type); new Handle:datapack = CreateDataPack(); WritePackString(datapack, steamid); diff --git a/gameserver/addons/sourcemod/scripting/timer-mapchooser.sp b/gameserver/addons/sourcemod/scripting/timer-mapchooser.sp new file mode 100644 index 0000000..acb35cc --- /dev/null +++ b/gameserver/addons/sourcemod/scripting/timer-mapchooser.sp @@ -0,0 +1,2192 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * MapChooser Extended + * Creates a map vote at appropriate times, setting sm_nextmap to the winning + * vote. Includes extra options not present in the SourceMod MapChooser + * + * MapChooser Extended (C)2011-2013 Powerlord (Ross Bemrose) + * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +//#define DEBUG + +#if defined DEBUG + #define assert(%1) if (!(%1)) ThrowError("Debug Assertion Failed"); + #define assert_msg(%1,%2) if (!(%1)) ThrowError(%2); +#else + #define assert(%1) + #define assert_msg(%1,%2) +#endif + +#pragma semicolon 1 +#include +#include +#include +#include +#include +#include +#include + +#undef REQUIRE_PLUGIN +#include + +#define MCE_VERSION "1.10.2" + +#define NV "nativevotes" + +enum RoundCounting +{ + RoundCounting_Standard = 0, + RoundCounting_MvM, + RoundCounting_ArmsRace, +} + +// CSGO requires two cvars to get the game type +enum +{ + GameType_Classic = 0, + GameType_GunGame = 1, + GameType_Training = 2, + GameType_Custom = 3, +} + +enum +{ + GunGameMode_ArmsRace = 0, + GunGameMode_Demolition = 1, + GunGameMode_DeathMatch = 2, +} + +public Plugin:myinfo = +{ + name = "MapChooser Extended", + author = "Powerlord, Zuko, and AlliedModders LLC", + description = "Automated Map Voting with Extensions", + version = MCE_VERSION, + url = "https://forums.alliedmods.net/showthread.php?t=156974" +}; + +/* Valve ConVars */ +new Handle:g_Cvar_Winlimit = INVALID_HANDLE; +new Handle:g_Cvar_Maxrounds = INVALID_HANDLE; +new Handle:g_Cvar_Fraglimit = INVALID_HANDLE; +new Handle:g_Cvar_Bonusroundtime = INVALID_HANDLE; +new Handle:g_Cvar_MatchClinch = INVALID_HANDLE; +new Handle:g_Cvar_VoteNextLevel = INVALID_HANDLE; +new Handle:g_Cvar_GameType = INVALID_HANDLE; +new Handle:g_Cvar_GameMode = INVALID_HANDLE; + +/* Plugin ConVars */ +new Handle:g_Cvar_StartTime = INVALID_HANDLE; +new Handle:g_Cvar_StartRounds = INVALID_HANDLE; +new Handle:g_Cvar_StartFrags = INVALID_HANDLE; +new Handle:g_Cvar_ExtendTimeStep = INVALID_HANDLE; +new Handle:g_Cvar_ExtendRoundStep = INVALID_HANDLE; +new Handle:g_Cvar_ExtendFragStep = INVALID_HANDLE; +new Handle:g_Cvar_ExcludeMaps = INVALID_HANDLE; +new Handle:g_Cvar_IncludeMaps = INVALID_HANDLE; +new Handle:g_Cvar_NoVoteMode = INVALID_HANDLE; +new Handle:g_Cvar_Extend = INVALID_HANDLE; +new Handle:g_Cvar_DontChange = INVALID_HANDLE; +new Handle:g_Cvar_EndOfMapVote = INVALID_HANDLE; +new Handle:g_Cvar_VoteDuration = INVALID_HANDLE; + +new Handle:g_VoteTimer = INVALID_HANDLE; +new Handle:g_RetryTimer = INVALID_HANDLE; +new Handle:g_WarningTimer = INVALID_HANDLE; + +/* Data Handles */ +new Handle:g_MapList = INVALID_HANDLE; +new Handle:g_NominateList = INVALID_HANDLE; +new Handle:g_NominateOwners = INVALID_HANDLE; +new Handle:g_OldMapList = INVALID_HANDLE; +new Handle:g_NextMapList = INVALID_HANDLE; +new Handle:g_VoteMenu = INVALID_HANDLE; + +new g_Extends; +new g_TotalRounds; +new bool:g_HasVoteStarted; +new bool:g_WaitingForVote; +new bool:g_MapVoteCompleted; +new bool:g_ChangeMapAtRoundEnd; +new bool:g_ChangeMapInProgress; +new bool:g_HasIntermissionStarted = false; +new g_mapFileSerial = -1; + +new g_NominateCount = 0; +new MapChange:g_ChangeTime; + +new Handle:g_NominationsResetForward = INVALID_HANDLE; +new Handle:g_MapVoteStartedForward = INVALID_HANDLE; + +/* Mapchooser Extended Plugin ConVars */ + +new Handle:g_Cvar_RunOff = INVALID_HANDLE; +new Handle:g_Cvar_RunOffPercent = INVALID_HANDLE; +new Handle:g_Cvar_BlockSlots = INVALID_HANDLE; +new Handle:g_Cvar_MaxRunOffs = INVALID_HANDLE; +new Handle:g_Cvar_StartTimePercent = INVALID_HANDLE; +new Handle:g_Cvar_StartTimePercentEnable = INVALID_HANDLE; +new Handle:g_Cvar_WarningTime = INVALID_HANDLE; +new Handle:g_Cvar_RunOffWarningTime = INVALID_HANDLE; +new Handle:g_Cvar_MenuStyle = INVALID_HANDLE; +new Handle:g_Cvar_TimerLocation = INVALID_HANDLE; +new Handle:g_Cvar_ExtendPosition = INVALID_HANDLE; +new Handle:g_Cvar_MarkCustomMaps = INVALID_HANDLE; +new Handle:g_Cvar_RandomizeNominations = INVALID_HANDLE; +new Handle:g_Cvar_HideTimer = INVALID_HANDLE; +new Handle:g_Cvar_NoVoteOption = INVALID_HANDLE; + +/* Mapchooser Extended Data Handles */ +new Handle:g_OfficialList = INVALID_HANDLE; + +/* Mapchooser Extended Forwards */ +new Handle:g_MapVoteWarningStartForward = INVALID_HANDLE; +new Handle:g_MapVoteWarningTickForward = INVALID_HANDLE; +new Handle:g_MapVoteStartForward = INVALID_HANDLE; +new Handle:g_MapVoteEndForward = INVALID_HANDLE; +new Handle:g_MapVoteRunoffStartForward = INVALID_HANDLE; + +/* Mapchooser Extended Globals */ +new g_RunoffCount = 0; +new g_mapOfficialFileSerial = -1; +new bool:g_NativeVotes = false; +new String:g_GameModName[64]; +new bool:g_WarningInProgress = false; +new bool:g_AddNoVote = false; + +new RoundCounting:g_RoundCounting = RoundCounting_Standard; + +/* Upper bound of how many team there could be */ +#define MAXTEAMS 10 +new g_winCount[MAXTEAMS]; + +new bool:g_BlockedSlots = false; +new g_ObjectiveEnt = -1; + +enum TimerLocation +{ + TimerLocation_Hint = 0, + TimerLocation_Center = 1, + TimerLocation_Chat = 2, +} + +enum WarningType +{ + WarningType_Vote, + WarningType_Revote, +} + +#define VOTE_EXTEND "##extend##" +#define VOTE_DONTCHANGE "##dontchange##" + +/* Mapchooser Extended Defines */ +#define LINE_ONE "##lineone##" +#define LINE_TWO "##linetwo##" +#define LINE_SPACER "##linespacer##" +#define FAILURE_TIMER_LENGTH 5 + +public OnPluginStart() +{ + LoadTranslations("mapchooser_extended.phrases"); + LoadTranslations("basevotes.phrases"); + LoadTranslations("common.phrases"); + + new arraySize = ByteCountToCells(PLATFORM_MAX_PATH); + g_MapList = CreateArray(arraySize); + g_NominateList = CreateArray(arraySize); + g_NominateOwners = CreateArray(1); + g_OldMapList = CreateArray(arraySize); + g_NextMapList = CreateArray(arraySize); + g_OfficialList = CreateArray(arraySize); + + GetGameFolderName(g_GameModName, sizeof(g_GameModName)); + + g_Cvar_EndOfMapVote = CreateConVar("mce_endvote", "1", "Specifies if MapChooser should run an end of map vote", _, true, 0.0, true, 1.0); + + g_Cvar_StartTime = CreateConVar("mce_starttime", "10.0", "Specifies when to start the vote based on time remaining.", _, true, 1.0); + g_Cvar_StartRounds = CreateConVar("mce_startround", "2.0", "Specifies when to start the vote based on rounds remaining. Use 0 on DoD:S, CS:S, and TF2 to start vote during bonus round time", _, true, 0.0); + g_Cvar_StartFrags = CreateConVar("mce_startfrags", "5.0", "Specifies when to start the vote base on frags remaining.", _, true, 1.0); + g_Cvar_ExtendTimeStep = CreateConVar("mce_extend_timestep", "15", "Specifies how much many more minutes each extension makes", _, true, 5.0); + g_Cvar_ExtendRoundStep = CreateConVar("mce_extend_roundstep", "5", "Specifies how many more rounds each extension makes", _, true, 1.0); + g_Cvar_ExtendFragStep = CreateConVar("mce_extend_fragstep", "10", "Specifies how many more frags are allowed when map is extended.", _, true, 5.0); + g_Cvar_ExcludeMaps = CreateConVar("mce_exclude", "5", "Specifies how many past maps to exclude from the vote.", _, true, 0.0); + g_Cvar_IncludeMaps = CreateConVar("mce_include", "5", "Specifies how many maps to include in the vote.", _, true, 2.0, true, 6.0); + g_Cvar_NoVoteMode = CreateConVar("mce_novote", "1", "Specifies whether or not MapChooser should pick a map if no votes are received.", _, true, 0.0, true, 1.0); + g_Cvar_Extend = CreateConVar("mce_extend", "0", "Number of extensions allowed each map.", _, true, 0.0); + g_Cvar_DontChange = CreateConVar("mce_dontchange", "1", "Specifies if a 'Don't Change' option should be added to early votes", _, true, 0.0); + g_Cvar_VoteDuration = CreateConVar("mce_voteduration", "20", "Specifies how long the mapvote should be available for.", _, true, 5.0); + + // MapChooser Extended cvars + CreateConVar("mce_version", MCE_VERSION, "MapChooser Extended Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_NOTIFY|FCVAR_DONTRECORD); + + g_Cvar_RunOff = CreateConVar("mce_runoff", "1", "Hold run off votes if winning choice has less than a certain percentage of votes", _, true, 0.0, true, 1.0); + g_Cvar_RunOffPercent = CreateConVar("mce_runoffpercent", "50", "If winning choice has less than this percent of votes, hold a runoff", _, true, 0.0, true, 100.0); + g_Cvar_BlockSlots = CreateConVar("mce_blockslots", "1", "Block slots to prevent accidental votes. Only applies when Voice Command style menus are in use.", _, true, 0.0, true, 1.0); + //g_Cvar_BlockSlotsCount = CreateConVar("mce_blockslots_count", "2", "Number of slots to block.", _, true, 1.0, true, 3.0); + g_Cvar_MaxRunOffs = CreateConVar("mce_maxrunoffs", "1", "Number of run off votes allowed each map.", _, true, 0.0); + g_Cvar_StartTimePercent = CreateConVar("mce_start_percent", "35.0", "Specifies when to start the vote based on percents.", _, true, 0.0, true, 100.0); + g_Cvar_StartTimePercentEnable = CreateConVar("mce_start_percent_enable", "0", "Enable or Disable percentage calculations when to start vote.", _, true, 0.0, true, 1.0); + g_Cvar_WarningTime = CreateConVar("mce_warningtime", "15.0", "Warning time in seconds.", _, true, 0.0, true, 60.0); + g_Cvar_RunOffWarningTime = CreateConVar("mce_runoffvotewarningtime", "5.0", "Warning time for runoff vote in seconds.", _, true, 0.0, true, 30.0); + g_Cvar_MenuStyle = CreateConVar("mce_menustyle", "0", "Menu Style. 0 is the game's default, 1 is the older Valve style that requires you to press Escape to see the menu, 2 is the newer 1-9 button Voice Command style, unavailable in some games. Ignored on TF2 if NativeVotes Plugin is loaded.", _, true, 0.0, true, 2.0); + g_Cvar_TimerLocation = CreateConVar("mce_warningtimerlocation", "0", "Location for the warning timer text. 0 is HintBox, 1 is Center text, 2 is Chat. Defaults to HintBox.", _, true, 0.0, true, 2.0); + g_Cvar_MarkCustomMaps = CreateConVar("mce_markcustommaps", "1", "Mark custom maps in the vote list. 0 = Disabled, 1 = Mark with *, 2 = Mark with phrase.", _, true, 0.0, true, 2.0); + g_Cvar_ExtendPosition = CreateConVar("mce_extendposition", "0", "Position of Extend/Don't Change options. 0 = at end, 1 = at start.", _, true, 0.0, true, 1.0); + g_Cvar_RandomizeNominations = CreateConVar("mce_randomizeorder", "0", "Randomize map order?", _, true, 0.0, true, 1.0); + g_Cvar_HideTimer = CreateConVar("mce_hidetimer", "0", "Hide the MapChooser Extended warning timer", _, true, 0.0, true, 1.0); + g_Cvar_NoVoteOption = CreateConVar("mce_addnovote", "1", "Add \"No Vote\" to vote menu?", _, true, 0.0, true, 1.0); + + RegAdminCmd("sm_mapvote", Command_Mapvote, ADMFLAG_CHANGEMAP, "sm_mapvote - Forces MapChooser to attempt to run a map vote now."); + RegAdminCmd("sm_setnextmap", Command_SetNextmap, ADMFLAG_CHANGEMAP, "sm_setnextmap "); + + // Mapchooser Extended Commands + RegAdminCmd("mce_reload_maplist", Command_ReloadMaps, ADMFLAG_CHANGEMAP, "mce_reload_maplist - Reload the Official Maplist file."); + + g_Cvar_Winlimit = FindConVar("mp_winlimit"); + g_Cvar_Maxrounds = FindConVar("mp_maxrounds"); + g_Cvar_Fraglimit = FindConVar("mp_fraglimit"); + + decl String:mapListPath[PLATFORM_MAX_PATH]; + + BuildPath(Path_SM, mapListPath, PLATFORM_MAX_PATH, "configs/mapchooser_extended/maps/%s.txt", g_GameModName); + SetMapListCompatBind("official", mapListPath); + + if (GetEngineVersion() == Engine_CSGO) + { + g_Cvar_VoteNextLevel = FindConVar("mp_endmatch_votenextmap"); + g_Cvar_GameType = FindConVar("game_type"); + g_Cvar_GameMode = FindConVar("game_mode"); + g_Cvar_Bonusroundtime = FindConVar("mp_round_restart_delay"); + } + else if (GetEngineVersion() == Engine_CSS) + { + g_Cvar_Bonusroundtime = FindConVar("mp_round_restart_delay"); + } + + if (g_Cvar_Winlimit != INVALID_HANDLE || g_Cvar_Maxrounds != INVALID_HANDLE) + { + if (GetEngineVersion() == Engine_CSGO) + { + HookEvent("round_end", Event_RoundEnd); + HookEvent("cs_intermission", Event_Intermission); + HookEvent("announce_phase_end", Event_PhaseEnd); + g_Cvar_MatchClinch = FindConVar("mp_match_can_clinch"); + } + + else if (GetEngineVersion() == Engine_CSS) + HookEvent("round_end", Event_RoundEnd); + } + + if (g_Cvar_Fraglimit != INVALID_HANDLE) + { + HookEvent("player_death", Event_PlayerDeath); + } + + AutoExecConfig(true, "mapchooser_extended"); + + //Change the mp_bonusroundtime max so that we have time to display the vote + //If you display a vote during bonus time good defaults are 17 vote duration and 19 mp_bonustime + if (g_Cvar_Bonusroundtime != INVALID_HANDLE) + { + SetConVarBounds(g_Cvar_Bonusroundtime, ConVarBound_Upper, true, 30.0); + } + + g_NominationsResetForward = CreateGlobalForward("OnNominationRemoved", ET_Ignore, Param_String, Param_Cell); + g_MapVoteStartedForward = CreateGlobalForward("OnMapVoteStarted", ET_Ignore); + + //MapChooser Extended Forwards + g_MapVoteStartForward = CreateGlobalForward("OnMapVoteStart", ET_Ignore); // Deprecated + g_MapVoteEndForward = CreateGlobalForward("OnMapVoteEnd", ET_Ignore, Param_String); + g_MapVoteWarningStartForward = CreateGlobalForward("OnMapVoteWarningStart", ET_Ignore); + g_MapVoteWarningTickForward = CreateGlobalForward("OnMapVoteWarningTick", ET_Ignore, Param_Cell); + g_MapVoteRunoffStartForward = CreateGlobalForward("OnMapVoteRunnoffWarningStart", ET_Ignore); + +} + +public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) +{ + if (LibraryExists("mapchooser")) + { + strcopy(error, err_max, "MapChooser already loaded, aborting."); + return APLRes_Failure; + } + + RegPluginLibrary("mapchooser"); + + MarkNativeAsOptional("GetEngineVersion"); + + CreateNative("NominateMap", Native_NominateMap); + CreateNative("RemoveNominationByMap", Native_RemoveNominationByMap); + CreateNative("RemoveNominationByOwner", Native_RemoveNominationByOwner); + CreateNative("InitiateMapChooserVote", Native_InitiateVote); + CreateNative("CanMapChooserStartVote", Native_CanVoteStart); + CreateNative("HasEndOfMapVoteFinished", Native_CheckVoteDone); + CreateNative("GetExcludeMapList", Native_GetExcludeMapList); + CreateNative("GetNominatedMapList", Native_GetNominatedMapList); + CreateNative("EndOfMapVoteEnabled", Native_EndOfMapVoteEnabled); + + // MapChooser Extended natives + CreateNative("IsMapOfficial", Native_IsMapOfficial); + CreateNative("CanNominate", Native_CanNominate); + + return APLRes_Success; +} + +public OnAllPluginsLoaded() +{ + g_NativeVotes = LibraryExists(NV) && NativeVotes_IsVoteTypeSupported(NativeVotesType_NextLevelMult); +} + +public OnLibraryAdded(const String:name[]) +{ + if (StrEqual(name, NV) && NativeVotes_IsVoteTypeSupported(NativeVotesType_NextLevelMult)) + { + g_NativeVotes = true; + } +} + +public OnLibraryRemoved(const String:name[]) +{ + if (StrEqual(name, NV)) + { + g_NativeVotes = false; + } +} + +public OnMapStart() +{ + decl String:folder[64]; + GetGameFolderName(folder, sizeof(folder)); + + g_RoundCounting = RoundCounting_Standard; + g_ObjectiveEnt = -1; + + if (strcmp(folder, "csgo") == 0 && GetConVarInt(g_Cvar_GameType) == GameType_GunGame && + GetConVarInt(g_Cvar_GameMode) == GunGameMode_ArmsRace) + { + g_RoundCounting = RoundCounting_ArmsRace; + } +} + +public OnConfigsExecuted() +{ + if (ReadMapList(g_MapList, + g_mapFileSerial, + "mapchooser", + MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_MAPSFOLDER) + != INVALID_HANDLE) + + { + if (g_mapFileSerial == -1) + { + LogError("Unable to create a valid map list."); + } + } + + // Disable the next level vote in CS:GO + if (g_Cvar_VoteNextLevel != INVALID_HANDLE) + { + SetConVarBool(g_Cvar_VoteNextLevel, false); + } + + CreateNextVote(); + SetupTimeleftTimer(); + + g_TotalRounds = 0; + + g_Extends = 0; + + g_MapVoteCompleted = false; + + g_NominateCount = 0; + ClearArray(g_NominateList); + ClearArray(g_NominateOwners); + + for (new i=0; i GetConVarInt(g_Cvar_ExcludeMaps)) + { + RemoveFromArray(g_OldMapList, 0); + } +} + +public OnClientDisconnect(client) +{ + new index = FindValueInArray(g_NominateOwners, client); + + if (index == -1) + { + return; + } + + new String:oldmap[PLATFORM_MAX_PATH]; + GetArrayString(g_NominateList, index, oldmap, PLATFORM_MAX_PATH); + Call_StartForward(g_NominationsResetForward); + Call_PushString(oldmap); + Call_PushCell(GetArrayCell(g_NominateOwners, index)); + Call_Finish(); + + RemoveFromArray(g_NominateOwners, index); + RemoveFromArray(g_NominateList, index); + g_NominateCount--; +} + +public Action:Command_SetNextmap(client, args) +{ + if (args < 1) + { + CReplyToCommand(client, "[MCE] Usage: sm_setnextmap "); + return Plugin_Handled; + } + + decl String:map[PLATFORM_MAX_PATH]; + GetCmdArg(1, map, PLATFORM_MAX_PATH); + + if (!IsMapValid(map)) + { + CReplyToCommand(client, "[MCE] %t", "Map was not found", map); + return Plugin_Handled; + } + + ShowActivity(client, "%t", "Changed Next Map", map); + LogAction(client, -1, "\"%L\" changed nextmap to \"%s\"", client, map); + + SetNextMap(map); + g_MapVoteCompleted = true; + + return Plugin_Handled; +} + +public Action:Command_ReloadMaps(client, args) +{ + InitializeOfficialMapList(); +} + +public OnMapTimeLeftChanged() +{ + if (GetArraySize(g_MapList)) + { + SetupTimeleftTimer(); + } +} + +SetupTimeleftTimer() +{ + new time; + if (GetMapTimeLeft(time) && time > 0) + { + new startTime; + if (GetConVarBool(g_Cvar_StartTimePercentEnable)) + { + new timeLimit; + if (GetMapTimeLimit(timeLimit) && timeLimit > 0) + { + startTime = GetConVarInt(g_Cvar_StartTimePercent) * (timeLimit * 60) / 100; + } + } + else + { + startTime = GetConVarInt(g_Cvar_StartTime) * 60; + } + + if (time - startTime < 0 && GetConVarBool(g_Cvar_EndOfMapVote) && !g_MapVoteCompleted && !g_HasVoteStarted) + { + SetupWarningTimer(WarningType_Vote); + } + else + { + if (g_WarningTimer == INVALID_HANDLE) + { + if (g_VoteTimer != INVALID_HANDLE) + { + KillTimer(g_VoteTimer); + g_VoteTimer = INVALID_HANDLE; + } + + //g_VoteTimer = CreateTimer(float(time - startTime), Timer_StartMapVoteTimer_StartMapVote, _, TIMER_FLAG_NO_MAPCHANGE); + g_VoteTimer = CreateTimer(float(time - startTime), Timer_StartWarningTimer, _, TIMER_FLAG_NO_MAPCHANGE); + } + } + } +} + +public Action:Timer_StartWarningTimer(Handle:timer) +{ + g_VoteTimer = INVALID_HANDLE; + + if (!g_WarningInProgress || g_WarningTimer == INVALID_HANDLE) + { + SetupWarningTimer(WarningType_Vote); + } +} + +public Action:Timer_StartMapVote(Handle:timer, Handle:data) +{ + static timePassed; + + // This is still necessary because InitiateVote still calls this directly via the retry timer + if (!GetArraySize(g_MapList) || !GetConVarBool(g_Cvar_EndOfMapVote) || g_MapVoteCompleted || g_HasVoteStarted) + { + g_WarningTimer = INVALID_HANDLE; + return Plugin_Stop; + } + + ResetPack(data); + new warningMaxTime = ReadPackCell(data); + new warningTimeRemaining = warningMaxTime - timePassed; + + new String:warningPhrase[32]; + ReadPackString(data, warningPhrase, sizeof(warningPhrase)); + + // Tick timer for external plugins + Call_StartForward(g_MapVoteWarningTickForward); + Call_PushCell(warningTimeRemaining); + Call_Finish(); + + if (timePassed == 0 || !GetConVarBool(g_Cvar_HideTimer)) + { + new TimerLocation:timerLocation = TimerLocation:GetConVarInt(g_Cvar_TimerLocation); + + switch(timerLocation) + { + case TimerLocation_Center: + { + PrintCenterTextAll("%t", warningPhrase, warningTimeRemaining); + } + + case TimerLocation_Chat: + { + PrintToChatAll("%t", warningPhrase, warningTimeRemaining); + } + + default: + { + PrintHintTextToAll("%t", warningPhrase, warningTimeRemaining); + } + } + } + + if (timePassed++ >= warningMaxTime) + { + if (timer == g_RetryTimer) + { + g_WaitingForVote = false; + g_RetryTimer = INVALID_HANDLE; + } + else + { + g_WarningTimer = INVALID_HANDLE; + } + + timePassed = 0; + new MapChange:mapChange = MapChange:ReadPackCell(data); + new Handle:hndl = Handle:ReadPackCell(data); + + InitiateVote(mapChange, hndl); + + return Plugin_Stop; + } + return Plugin_Continue; +} + +public Event_TeamPlayWinPanel(Handle:event, const String:name[], bool:dontBroadcast) +{ + if (g_ChangeMapAtRoundEnd) + { + g_ChangeMapAtRoundEnd = false; + CreateTimer(2.0, Timer_ChangeMap, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE); + g_ChangeMapInProgress = true; + } + + new bluescore = GetEventInt(event, "blue_score"); + new redscore = GetEventInt(event, "red_score"); + + if(GetEventInt(event, "round_complete") == 1 || StrEqual(name, "arena_win_panel")) + { + g_TotalRounds++; + + if (!GetArraySize(g_MapList) || g_HasVoteStarted || g_MapVoteCompleted || !GetConVarBool(g_Cvar_EndOfMapVote)) + { + return; + } + + CheckMaxRounds(g_TotalRounds); + + switch(GetEventInt(event, "winning_team")) + { + case 3: + { + CheckWinLimit(bluescore); + } + case 2: + { + CheckWinLimit(redscore); + } + //We need to do nothing on winning_team == 0 this indicates stalemate. + default: + { + return; + } + } + } +} + +public Event_MvMWinPanel(Handle:event, const String:name[], bool:dontBroadcast) +{ + if (GetEventInt(event, "winning_team") == 2) + { + new objectiveEnt = EntRefToEntIndex(g_ObjectiveEnt); + if (objectiveEnt != INVALID_ENT_REFERENCE) + { + g_TotalRounds = GetEntProp(g_ObjectiveEnt, Prop_Send, "m_nMannVsMachineWaveCount"); + CheckMaxRounds(g_TotalRounds); + } + } +} + +public Event_Intermission(Handle:event, const String:name[], bool:dontBroadcast) +{ + g_HasIntermissionStarted = true; +} + +public Event_PhaseEnd(Handle:event, const String:name[], bool:dontBroadcast) +{ + /* announce_phase_end fires for both half time and the end of the map, but intermission fires first for end of the map. */ + if (g_HasIntermissionStarted) + { + return; + } + + /* No intermission yet, so this must be half time. Swap the score counters. */ + new t_score = g_winCount[2]; + g_winCount[2] = g_winCount[3]; + g_winCount[3] = t_score; +} + +public Event_WeaponRank(Handle:event, const String:name[], bool:dontBroadcast) +{ + new rank = GetEventInt(event, "weaponrank"); + if (rank > g_TotalRounds) + { + g_TotalRounds = rank; + CheckMaxRounds(g_TotalRounds); + } +} + +/* You ask, why don't you just use team_score event? And I answer... Because CSS doesn't. */ +public Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) +{ + if (g_RoundCounting == RoundCounting_ArmsRace) + { + return; + } + + if (g_ChangeMapAtRoundEnd) + { + g_ChangeMapAtRoundEnd = false; + CreateTimer(2.0, Timer_ChangeMap, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE); + g_ChangeMapInProgress = true; + } + + new winner; + if (strcmp(name, "round_win") == 0 || strcmp(name, "dod_round_win") == 0) + { + // Nuclear Dawn & DoD:S + winner = GetEventInt(event, "team"); + } + else + { + winner = GetEventInt(event, "winner"); + } + + if (winner == 0 || winner == 1 || !GetConVarBool(g_Cvar_EndOfMapVote)) + { + return; + } + + if (winner >= MAXTEAMS) + { + SetFailState("Mod exceed maximum team count - Please file a bug report."); + } + + g_TotalRounds++; + + g_winCount[winner]++; + + if (!GetArraySize(g_MapList) || g_HasVoteStarted || g_MapVoteCompleted) + { + return; + } + + CheckWinLimit(g_winCount[winner]); + CheckMaxRounds(g_TotalRounds); +} + +public CheckWinLimit(winner_score) +{ + if (g_Cvar_Winlimit != INVALID_HANDLE) + { + new winlimit = GetConVarInt(g_Cvar_Winlimit); + if (winlimit) + { + if (winner_score >= (winlimit - GetConVarInt(g_Cvar_StartRounds))) + { + if (!g_WarningInProgress || g_WarningTimer == INVALID_HANDLE) + { + SetupWarningTimer(WarningType_Vote, MapChange_MapEnd); + //InitiateVote(MapChange_MapEnd, INVALID_HANDLE); + } + } + } + } + + if (g_Cvar_MatchClinch != INVALID_HANDLE && g_Cvar_Maxrounds != INVALID_HANDLE) + { + new bool:clinch = GetConVarBool(g_Cvar_MatchClinch); + + if (clinch) + { + new maxrounds = GetConVarInt(g_Cvar_Maxrounds); + new winlimit = RoundFloat(maxrounds / 2.0); + + if(winner_score == winlimit - 1) + { + if (!g_WarningInProgress || g_WarningTimer == INVALID_HANDLE) + { + SetupWarningTimer(WarningType_Vote, MapChange_MapEnd); + //InitiateVote(MapChange_MapEnd, INVALID_HANDLE); + } + } + } + } +} + +public CheckMaxRounds(roundcount) +{ + new maxrounds = 0; + + if (g_RoundCounting == RoundCounting_ArmsRace) + { + maxrounds = GameRules_GetProp("m_iNumGunGameProgressiveWeaponsCT"); + } + else if (g_RoundCounting == RoundCounting_MvM) + { + maxrounds = GetEntProp(g_ObjectiveEnt, Prop_Send, "m_nMannVsMachineMaxWaveCount"); + } + else if (g_Cvar_Maxrounds != INVALID_HANDLE) + { + maxrounds = GetConVarInt(g_Cvar_Maxrounds); + } + else + { + return; + } + + if (maxrounds) + { + if (roundcount >= (maxrounds - GetConVarInt(g_Cvar_StartRounds))) + { + if (!g_WarningInProgress || g_WarningTimer == INVALID_HANDLE) + { + SetupWarningTimer(WarningType_Vote, MapChange_MapEnd); + //InitiateVote(MapChange_MapEnd, INVALID_HANDLE); + } + } + } +} + +public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) +{ + if (!GetArraySize(g_MapList) || g_Cvar_Fraglimit == INVALID_HANDLE || g_HasVoteStarted) + { + return; + } + + if (!GetConVarInt(g_Cvar_Fraglimit) || !GetConVarBool(g_Cvar_EndOfMapVote)) + { + return; + } + + if (g_MapVoteCompleted) + { + return; + } + + new fragger = GetClientOfUserId(GetEventInt(event, "attacker")); + + if (!fragger) + { + return; + } + + if (GetClientFrags(fragger) >= (GetConVarInt(g_Cvar_Fraglimit) - GetConVarInt(g_Cvar_StartFrags))) + { + if (!g_WarningInProgress || g_WarningTimer == INVALID_HANDLE) + { + SetupWarningTimer(WarningType_Vote, MapChange_MapEnd); + //InitiateVote(MapChange_MapEnd, INVALID_HANDLE); + } + } +} + +public Action:Command_Mapvote(client, args) +{ + ShowActivity2(client, "[MCE] ", "%t", "Initiated Vote Map"); + + SetupWarningTimer(WarningType_Vote, MapChange_MapEnd, INVALID_HANDLE, true); + + //InitiateVote(MapChange_MapEnd, INVALID_HANDLE); + + return Plugin_Handled; +} + +/** + * Starts a new map vote + * + * @param when When the resulting map change should occur. + * @param inputlist Optional list of maps to use for the vote, otherwise an internal list of nominations + random maps will be used. + */ +InitiateVote(MapChange:when, Handle:inputlist=INVALID_HANDLE) +{ + g_WaitingForVote = true; + g_WarningInProgress = false; + + // Check if a nativevotes vots is in progress first + // NativeVotes running at the same time as a regular vote can cause hintbox problems, + // so always check for a standard vote + if (IsVoteInProgress() || (g_NativeVotes && NativeVotes_IsVoteInProgress())) + { + // Can't start a vote, try again in 5 seconds. + //g_RetryTimer = CreateTimer(5.0, Timer_StartMapVote, _, TIMER_FLAG_NO_MAPCHANGE); + + CPrintToChatAll("[MCE] %t", "Cannot Start Vote", FAILURE_TIMER_LENGTH); + new Handle:data; + g_RetryTimer = CreateDataTimer(1.0, Timer_StartMapVote, data, TIMER_FLAG_NO_MAPCHANGE | TIMER_REPEAT); + + /* Mapchooser Extended */ + WritePackCell(data, FAILURE_TIMER_LENGTH); + + if (GetConVarBool(g_Cvar_RunOff) && g_RunoffCount > 0) + { + WritePackString(data, "Revote Warning"); + } else { + WritePackString(data, "Vote Warning"); + } + /* End Mapchooser Extended */ + + WritePackCell(data, _:when); + WritePackCell(data, _:inputlist); + ResetPack(data); + return; + } + + /* If the main map vote has completed (and chosen result) and its currently changing (not a delayed change) we block further attempts */ + if (g_MapVoteCompleted && g_ChangeMapInProgress) + { + return; + } + + g_ChangeTime = when; + + g_WaitingForVote = false; + + g_HasVoteStarted = true; + + if (g_NativeVotes) + { + g_VoteMenu = NativeVotes_Create(Handler_MapVoteMenu, NativeVotesType_NextLevelMult, MenuAction_End | MenuAction_VoteCancel | MenuAction_Display | MenuAction_DisplayItem); + NativeVotes_SetResultCallback(g_VoteMenu, Handler_NativeVoteFinished); + } + else + { + new Handle:menuStyle = GetMenuStyleHandle(MenuStyle:GetConVarInt(g_Cvar_MenuStyle)); + + if (menuStyle != INVALID_HANDLE) + { + g_VoteMenu = CreateMenuEx(menuStyle, Handler_MapVoteMenu, MenuAction_End | MenuAction_Display | MenuAction_DisplayItem | MenuAction_VoteCancel); + } + else + { + // You chose... poorly + g_VoteMenu = CreateMenu(Handler_MapVoteMenu, MenuAction_End | MenuAction_Display | MenuAction_DisplayItem | MenuAction_VoteCancel); + } + + g_AddNoVote = GetConVarBool(g_Cvar_NoVoteOption); + + // Block Vote Slots + if (GetConVarBool(g_Cvar_BlockSlots)) + { + new Handle:radioStyle = GetMenuStyleHandle(MenuStyle_Radio); + + if (GetMenuStyle(g_VoteMenu) == radioStyle) + { + g_BlockedSlots = true; + AddMenuItem(g_VoteMenu, LINE_ONE, "Choose something...", ITEMDRAW_DISABLED); + AddMenuItem(g_VoteMenu, LINE_TWO, "...will ya?", ITEMDRAW_DISABLED); + if (!g_AddNoVote) + { + AddMenuItem(g_VoteMenu, LINE_SPACER, "", ITEMDRAW_SPACER); + } + } else { + g_BlockedSlots = false; + } + } + + if (g_AddNoVote) + { + SetMenuOptionFlags(g_VoteMenu, MENUFLAG_BUTTON_NOVOTE); + } + + SetMenuTitle(g_VoteMenu, "Vote Nextmap"); + SetVoteResultCallback(g_VoteMenu, Handler_MapVoteFinished); + } + + /* Call OnMapVoteStarted() Forward */ +// Call_StartForward(g_MapVoteStartedForward); +// Call_Finish(); + + /** + * TODO: Make a proper decision on when to clear the nominations list. + * Currently it clears when used, and stays if an external list is provided. + * Is this the right thing to do? External lists will probably come from places + * like sm_mapvote from the adminmenu in the future. + */ + + decl String:map[PLATFORM_MAX_PATH]; + + /* No input given - User our internal nominations and maplist */ + if (inputlist == INVALID_HANDLE) + { + new Handle:randomizeList = INVALID_HANDLE; + if (GetConVarBool(g_Cvar_RandomizeNominations)) + { + randomizeList = CloneArray(g_NominateList); + } + + new nominateCount = GetArraySize(g_NominateList); + + new voteSize = GetVoteSize(); + + // The if and else if could be combined, but it looks extremely messy + // This is a hack to lower the vote menu size by 1 when Don't Change or Extend Map should appear + if (g_NativeVotes) + { + if ((when == MapChange_Instant || when == MapChange_RoundEnd) && GetConVarBool(g_Cvar_DontChange)) + { + voteSize--; + } + else if (GetConVarBool(g_Cvar_Extend) && g_Extends < GetConVarInt(g_Cvar_Extend)) + { + voteSize--; + } + } + + /* Smaller of the two - It should be impossible for nominations to exceed the size though (cvar changed mid-map?) */ + new nominationsToAdd = nominateCount >= voteSize ? voteSize : nominateCount; + + new bool:extendFirst = GetConVarBool(g_Cvar_ExtendPosition); + + if (extendFirst) + { + AddExtendToMenu(g_VoteMenu, when); + } + + for (new i=0; i= availableMaps) + { + //Run out of maps, this will have to do. + break; + } + } + + if (randomizeList != INVALID_HANDLE) + { + // Fisher-Yates Shuffle + for (new j = GetArraySize(randomizeList) - 1; j >= 1; j--) + { + new k = GetRandomInt(0, j); + SwapArrayItems(randomizeList, j, k); + } + + for (new j = 0; j < GetArraySize(randomizeList); j++) + { + GetArrayString(randomizeList, j, map, PLATFORM_MAX_PATH); + AddMapItem(map); + } + + CloseHandle(randomizeList); + randomizeList = INVALID_HANDLE; + } + + /* Wipe out our nominations list - Nominations have already been informed of this */ + g_NominateCount = 0; + ClearArray(g_NominateOwners); + ClearArray(g_NominateList); + + if (!extendFirst) + { + AddExtendToMenu(g_VoteMenu, when); + } + } + else //We were given a list of maps to start the vote with + { + new size = GetArraySize(inputlist); + + for (new i=0; i 0) + { + ExtendMapTimeLimit(GetConVarInt(g_Cvar_ExtendTimeStep)*60); + } + } + + if (g_Cvar_Winlimit != INVALID_HANDLE) + { + new winlimit = GetConVarInt(g_Cvar_Winlimit); + if (winlimit) + { + SetConVarInt(g_Cvar_Winlimit, winlimit + GetConVarInt(g_Cvar_ExtendRoundStep)); + } + } + + if (g_Cvar_Maxrounds != INVALID_HANDLE) + { + new maxrounds = GetConVarInt(g_Cvar_Maxrounds); + if (maxrounds) + { + SetConVarInt(g_Cvar_Maxrounds, maxrounds + GetConVarInt(g_Cvar_ExtendRoundStep)); + } + } + + if (g_Cvar_Fraglimit != INVALID_HANDLE) + { + new fraglimit = GetConVarInt(g_Cvar_Fraglimit); + if (fraglimit) + { + SetConVarInt(g_Cvar_Fraglimit, fraglimit + GetConVarInt(g_Cvar_ExtendFragStep)); + } + } + + if (g_NativeVotes) + { + NativeVotes_DisplayPassEx(menu, NativeVotesPass_Extend); + } + + CPrintToChatAll("[MCE] %t", "Current Map Extended", RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100), num_votes); + LogAction(-1, -1, "Voting for next map has finished. The current map has been extended."); + + // We extended, so we'll have to vote again. + g_HasVoteStarted = false; + CreateNextVote(); + SetupTimeleftTimer(); + + } + else if (strcmp(map, VOTE_DONTCHANGE, false) == 0) + { + if (g_NativeVotes) + { + NativeVotes_DisplayPassEx(menu, NativeVotesPass_Extend); + } + + CPrintToChatAll("[MCE] %t", "Current Map Stays", RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100), num_votes); + LogAction(-1, -1, "Voting for next map has finished. 'No Change' was the winner"); + + g_HasVoteStarted = false; + CreateNextVote(); + SetupTimeleftTimer(); + } + else + { + if (g_ChangeTime == MapChange_MapEnd) + { + SetNextMap(map); + if (g_NativeVotes) + { + NativeVotes_DisplayPass(menu, map); + } + } + else if (g_ChangeTime == MapChange_Instant) + { + new Handle:data; + CreateDataTimer(4.0, Timer_ChangeMap, data); + WritePackString(data, map); + g_ChangeMapInProgress = false; + if (g_NativeVotes) + { + NativeVotes_DisplayPassEx(menu, NativeVotesPass_ChgLevel, map); + } + } + else // MapChange_RoundEnd + { + SetNextMap(map); + g_ChangeMapAtRoundEnd = true; + + if (g_NativeVotes) + { + NativeVotes_DisplayPass(menu, map); + } + } + + g_HasVoteStarted = false; + g_MapVoteCompleted = true; + + CPrintToChatAll("[MCE] %t", "Nextmap Voting Finished", map, RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100), num_votes); + LogAction(-1, -1, "Voting for next map has finished. Nextmap: %s.", map); + } +} + +public Handler_MapVoteFinished(Handle:menu, + num_votes, + num_clients, + const client_info[][2], + num_items, + const item_info[][2]) +{ + // Implement revote logic - Only run this` block if revotes are enabled and this isn't the last revote + if (GetConVarBool(g_Cvar_RunOff) && num_items > 1 && g_RunoffCount < GetConVarInt(g_Cvar_MaxRunOffs)) + { + g_RunoffCount++; + new highest_votes = item_info[0][VOTEINFO_ITEM_VOTES]; + new required_percent = GetConVarInt(g_Cvar_RunOffPercent); + new required_votes = RoundToCeil(float(num_votes) * float(required_percent) / 100); + + if (highest_votes == item_info[1][VOTEINFO_ITEM_VOTES]) + { + g_HasVoteStarted = false; + + //Revote is needed + new arraySize = ByteCountToCells(PLATFORM_MAX_PATH); + new Handle:mapList = CreateArray(arraySize); + + for (new i = 0; i < num_items; i++) + { + if (item_info[i][VOTEINFO_ITEM_VOTES] == highest_votes) + { + decl String:map[PLATFORM_MAX_PATH]; + + GetMapItem(menu, item_info[i][VOTEINFO_ITEM_INDEX], map, PLATFORM_MAX_PATH); + PushArrayString(mapList, map); + } + else + { + break; + } + } + + if (g_NativeVotes) + { + NativeVotes_DisplayFail(menu, NativeVotesFail_NotEnoughVotes); + } + + CPrintToChatAll("[MCE] %t", "Tie Vote", GetArraySize(mapList)); + SetupWarningTimer(WarningType_Revote, MapChange:g_ChangeTime, mapList); + return; + } + else if (highest_votes < required_votes) + { + g_HasVoteStarted = false; + + //Revote is needed + new arraySize = ByteCountToCells(PLATFORM_MAX_PATH); + new Handle:mapList = CreateArray(arraySize); + + decl String:map1[PLATFORM_MAX_PATH]; + GetMapItem(menu, item_info[0][VOTEINFO_ITEM_INDEX], map1, PLATFORM_MAX_PATH); + + PushArrayString(mapList, map1); + + // We allow more than two maps for a revote if they are tied + for (new i = 1; i < num_items; i++) + { + if (GetArraySize(mapList) < 2 || item_info[i][VOTEINFO_ITEM_VOTES] == item_info[i - 1][VOTEINFO_ITEM_VOTES]) + { + decl String:map[PLATFORM_MAX_PATH]; + GetMapItem(menu, item_info[i][VOTEINFO_ITEM_INDEX], map, PLATFORM_MAX_PATH); + PushArrayString(mapList, map); + } + else + { + break; + } + } + + if (g_NativeVotes) + { + NativeVotes_DisplayFail(menu, NativeVotesFail_NotEnoughVotes); + } + + CPrintToChatAll("[MCE] %t", "Revote Is Needed", required_percent); + SetupWarningTimer(WarningType_Revote, MapChange:g_ChangeTime, mapList); + return; + } + } + + // No revote needed, continue as normal. + Handler_VoteFinishedGeneric(menu, num_votes, num_clients, client_info, num_items, item_info); +} + +// This is shared by NativeVotes now, but NV doesn't support Display or DisplayItem +public Handler_MapVoteMenu(Handle:menu, MenuAction:action, param1, param2) +{ + switch (action) + { + case MenuAction_End: + { + g_VoteMenu = INVALID_HANDLE; + if (g_NativeVotes) + { + NativeVotes_Close(menu); + } + else + { + CloseHandle(menu); + } + } + + case MenuAction_Display: + { + // NativeVotes uses the standard TF2/CSGO vote screen + if (!g_NativeVotes) + { + decl String:buffer[255]; + Format(buffer, sizeof(buffer), "%T", "Vote Nextmap", param1); + new Handle:panel = Handle:param2; + SetPanelTitle(panel, buffer); + } + } + + case MenuAction_DisplayItem: + { + new String:map[PLATFORM_MAX_PATH]; + new String:buffer[255]; + new mark = GetConVarInt(g_Cvar_MarkCustomMaps); + + if (g_NativeVotes) + { + NativeVotes_GetItem(menu, param2, map, PLATFORM_MAX_PATH); + } + else + { + GetMenuItem(menu, param2, map, PLATFORM_MAX_PATH); + } + + if (StrEqual(map, VOTE_EXTEND, false)) + { + Format(buffer, sizeof(buffer), "%T", "Extend Map", param1); + } + else if (StrEqual(map, VOTE_DONTCHANGE, false)) + { + Format(buffer, sizeof(buffer), "%T", "Dont Change", param1); + } + // Mapchooser Extended + else if (StrEqual(map, LINE_ONE, false)) + { + Format(buffer, sizeof(buffer),"%T", "Line One", param1); + } + else if (StrEqual(map, LINE_TWO, false)) + { + Format(buffer, sizeof(buffer),"%T", "Line Two", param1); + } + // Note that the first part is to discard the spacer line + else if (!StrEqual(map, LINE_SPACER, false)) + { + new tier = Timer_GetMapTier(map, TRACK_NORMAL); + ReplaceString(map, sizeof(map), "surf_", "", false); + ReplaceString(map, sizeof(map), "bhop_", "", false); + ReplaceString(map, sizeof(map), "bh_", "", false); + ReplaceString(map, sizeof(map), "mg_", "", false); + + if(!InternalIsMapOfficial(map)) + { + if(tier > 0) + { + switch (mark) + { + case 1: + { + Format(buffer, sizeof(buffer), "%T [Tier:%d]", "Custom Marked", param1, map, tier); + } + + case 2: + { + Format(buffer, sizeof(buffer), "%T [Tier:%d]", "Custom", param1, map, tier); + } + } + } + else + { + switch (mark) + { + case 1: + { + Format(buffer, sizeof(buffer), "%T", "Custom Marked", param1, map); + } + + case 2: + { + Format(buffer, sizeof(buffer), "%T", "Custom", param1, map); + } + } + } + } + } + + if (buffer[0] != '\0') + { + if (g_NativeVotes) + { + NativeVotes_RedrawVoteItem(buffer); + return _:Plugin_Continue; + } + else + { + return RedrawMenuItem(buffer); + } + } + // End Mapchooser Extended + } + + case MenuAction_VoteCancel: + { + // If we receive 0 votes, pick at random. + if (param1 == VoteCancel_NoVotes && GetConVarBool(g_Cvar_NoVoteMode)) + { + new count; + if (g_NativeVotes) + { + count = NativeVotes_GetItemCount(menu); + } + else + { + count = GetMenuItemCount(menu); + } + + decl item; + decl String:map[PLATFORM_MAX_PATH]; + + do + { + new startInt = 0; + if (!g_NativeVotes && g_BlockedSlots) + { + if (g_AddNoVote) + { + startInt = 2; + } + else + { + startInt = 3; + } + } + item = GetRandomInt(startInt, count - 1); + if (g_NativeVotes) + { + NativeVotes_GetItem(menu, item, map, PLATFORM_MAX_PATH); + } + else + { + GetMenuItem(menu, item, map, PLATFORM_MAX_PATH); + } + } + while (strcmp(map, VOTE_EXTEND, false) == 0); + + SetNextMap(map); + g_MapVoteCompleted = true; + + if (g_NativeVotes) + { + NativeVotes_DisplayPass(menu, map); + } + } + else if (g_NativeVotes) + { + new NativeVotesFailType:reason = NativeVotesFail_Generic; + if (param1 == VoteCancel_NoVotes) + { + reason = NativeVotesFail_NotEnoughVotes; + } + + NativeVotes_DisplayFail(menu, reason); + } + else + { + // We were actually cancelled. I guess we do nothing. + } + + g_HasVoteStarted = false; + } + } + + return 0; +} + +public Action:Timer_ChangeMap(Handle:hTimer, Handle:dp) +{ + g_ChangeMapInProgress = false; + + new String:map[PLATFORM_MAX_PATH]; + + if (dp == INVALID_HANDLE) + { + if (!GetNextMap(map, PLATFORM_MAX_PATH)) + { + //No passed map and no set nextmap. fail! + return Plugin_Stop; + } + } + else + { + ResetPack(dp); + ReadPackString(dp, map, PLATFORM_MAX_PATH); + } + + ForceChangeLevel(map, "Map Vote"); + + return Plugin_Stop; +} + +bool:RemoveStringFromArray(Handle:array, String:str[]) +{ + new index = FindStringInArray(array, str); + if (index != -1) + { + RemoveFromArray(array, index); + return true; + } + + return false; +} + +CreateNextVote() +{ + assert(g_NextMapList) + ClearArray(g_NextMapList); + + decl String:map[PLATFORM_MAX_PATH]; + new Handle:tempMaps = CloneArray(g_MapList); + + GetCurrentMap(map, PLATFORM_MAX_PATH); + RemoveStringFromArray(tempMaps, map); + + if (GetConVarInt(g_Cvar_ExcludeMaps) && GetArraySize(tempMaps) > GetConVarInt(g_Cvar_ExcludeMaps)) + { + for (new i = 0; i < GetArraySize(g_OldMapList); i++) + { + GetArrayString(g_OldMapList, i, map, PLATFORM_MAX_PATH); + RemoveStringFromArray(tempMaps, map); + } + } + + new voteSize = GetVoteSize(); + new limit = (voteSize < GetArraySize(tempMaps) ? voteSize : GetArraySize(tempMaps)); + + for (new i = 0; i < limit; i++) + { + new b = GetRandomInt(0, GetArraySize(tempMaps) - 1); + GetArrayString(tempMaps, b, map, PLATFORM_MAX_PATH); + PushArrayString(g_NextMapList, map); + RemoveFromArray(tempMaps, b); + } + + CloseHandle(tempMaps); +} + +bool:CanVoteStart() +{ + if (g_WaitingForVote || g_HasVoteStarted) + { + return false; + } + + return true; +} + +NominateResult:InternalNominateMap(String:map[], bool:force, owner) +{ + if (!IsMapValid(map)) + { + return Nominate_InvalidMap; + } + + /* Map already in the vote */ + if (FindStringInArray(g_NominateList, map) != -1) + { + return Nominate_AlreadyInVote; + } + + new index; + + /* Look to replace an existing nomination by this client - Nominations made with owner = 0 aren't replaced */ + if (owner && ((index = FindValueInArray(g_NominateOwners, owner)) != -1)) + { + new String:oldmap[PLATFORM_MAX_PATH]; + GetArrayString(g_NominateList, index, oldmap, PLATFORM_MAX_PATH); + Call_StartForward(g_NominationsResetForward); + Call_PushString(oldmap); + Call_PushCell(owner); + Call_Finish(); + + SetArrayString(g_NominateList, index, map); + return Nominate_Replaced; + } + + /* Too many nominated maps. */ + if (g_NominateCount >= GetVoteSize() && !force) + { + return Nominate_VoteFull; + } + + PushArrayString(g_NominateList, map); + PushArrayCell(g_NominateOwners, owner); + g_NominateCount++; + + while (GetArraySize(g_NominateList) > GetVoteSize()) + { + new String:oldmap[PLATFORM_MAX_PATH]; + GetArrayString(g_NominateList, 0, oldmap, PLATFORM_MAX_PATH); + Call_StartForward(g_NominationsResetForward); + Call_PushString(oldmap); + Call_PushCell(GetArrayCell(g_NominateOwners, 0)); + Call_Finish(); + + RemoveFromArray(g_NominateList, 0); + RemoveFromArray(g_NominateOwners, 0); + } + + return Nominate_Added; +} + +/* Add natives to allow nominate and initiate vote to be call */ + +/* native bool:NominateMap(const String:map[], bool:force, &NominateError:error); */ +public Native_NominateMap(Handle:plugin, numParams) +{ + new len; + GetNativeStringLength(1, len); + + if (len <= 0) + { + return false; + } + + new String:map[len+1]; + GetNativeString(1, map, len+1); + + return _:InternalNominateMap(map, GetNativeCell(2), GetNativeCell(3)); +} + +bool:InternalRemoveNominationByMap(String:map[]) +{ + for (new i = 0; i < GetArraySize(g_NominateList); i++) + { + new String:oldmap[PLATFORM_MAX_PATH]; + GetArrayString(g_NominateList, i, oldmap, PLATFORM_MAX_PATH); + + if(strcmp(map, oldmap, false) == 0) + { + Call_StartForward(g_NominationsResetForward); + Call_PushString(oldmap); + Call_PushCell(GetArrayCell(g_NominateOwners, i)); + Call_Finish(); + + RemoveFromArray(g_NominateList, i); + RemoveFromArray(g_NominateOwners, i); + g_NominateCount--; + + return true; + } + } + + return false; +} + +/* native bool:RemoveNominationByMap(const String:map[]); */ +public Native_RemoveNominationByMap(Handle:plugin, numParams) +{ + new len; + GetNativeStringLength(1, len); + + if (len <= 0) + { + return false; + } + + new String:map[len+1]; + GetNativeString(1, map, len+1); + + return _:InternalRemoveNominationByMap(map); +} + +bool:InternalRemoveNominationByOwner(owner) +{ + new index; + + if (owner && ((index = FindValueInArray(g_NominateOwners, owner)) != -1)) + { + new String:oldmap[PLATFORM_MAX_PATH]; + GetArrayString(g_NominateList, index, oldmap, PLATFORM_MAX_PATH); + + Call_StartForward(g_NominationsResetForward); + Call_PushString(oldmap); + Call_PushCell(owner); + Call_Finish(); + + RemoveFromArray(g_NominateList, index); + RemoveFromArray(g_NominateOwners, index); + g_NominateCount--; + + return true; + } + + return false; +} + +/* native bool:RemoveNominationByOwner(owner); */ +public Native_RemoveNominationByOwner(Handle:plugin, numParams) +{ + return _:InternalRemoveNominationByOwner(GetNativeCell(1)); +} + +/* native InitiateMapChooserVote(); */ +public Native_InitiateVote(Handle:plugin, numParams) +{ + new MapChange:when = MapChange:GetNativeCell(1); + new Handle:inputarray = Handle:GetNativeCell(2); + + LogAction(-1, -1, "Starting map vote because outside request"); + + SetupWarningTimer(WarningType_Vote, when, inputarray); + //InitiateVote(when, inputarray); +} + +public Native_CanVoteStart(Handle:plugin, numParams) +{ + return CanVoteStart(); +} + +public Native_CheckVoteDone(Handle:plugin, numParams) +{ + return g_MapVoteCompleted; +} + +public Native_EndOfMapVoteEnabled(Handle:plugin, numParams) +{ + return GetConVarBool(g_Cvar_EndOfMapVote); +} + +public Native_GetExcludeMapList(Handle:plugin, numParams) +{ + new Handle:array = Handle:GetNativeCell(1); + + if (array == INVALID_HANDLE) + { + return; + } + new size = GetArraySize(g_OldMapList); + decl String:map[PLATFORM_MAX_PATH]; + + for (new i=0; i -1); +} + +public Native_IsWarningTimer(Handle:plugin, numParams) +{ + return g_WarningInProgress; +} + +public Native_CanNominate(Handle:plugin, numParams) +{ + if (g_HasVoteStarted) + { + return _:CanNominate_No_VoteInProgress; + } + + if (g_MapVoteCompleted) + { + return _:CanNominate_No_VoteComplete; + } + + if (g_NominateCount >= GetVoteSize()) + { + return _:CanNominate_No_VoteFull; + } + + return _:CanNominate_Yes; +} + + +stock AddMapItem(const String:map[]) +{ + if (g_NativeVotes) + { + NativeVotes_AddItem(g_VoteMenu, map, map); + } + else + { + decl String:display[32], String:sMap[32]; + strcopy(sMap, sizeof(sMap), map); + Format(display, sizeof(display), "%s [Tier:%d]", map, Timer_GetMapTier(sMap, TRACK_NORMAL)); + AddMenuItem(g_VoteMenu, map, display); + } +} + +stock GetMapItem(Handle:menu, position, String:map[], mapLen) +{ + if (g_NativeVotes) + { + NativeVotes_GetItem(menu, position, map, mapLen); + } + else + { + GetMenuItem(menu, position, map, mapLen); + } +} + +stock AddExtendToMenu(Handle:menu, MapChange:when) +{ + /* Do we add any special items? */ + // Moved for Mapchooser Extended + + if ((when == MapChange_Instant || when == MapChange_RoundEnd) && GetConVarBool(g_Cvar_DontChange)) + { + if (g_NativeVotes) + { + // Built-in votes don't have "Don't Change", send Extend instead + NativeVotes_AddItem(menu, VOTE_DONTCHANGE, "Don't Change"); + } + else + { + AddMenuItem(menu, VOTE_DONTCHANGE, "Don't Change"); + } + } + else if (GetConVarBool(g_Cvar_Extend) && g_Extends < GetConVarInt(g_Cvar_Extend)) + { + if (g_NativeVotes) + { + NativeVotes_AddItem(menu, VOTE_EXTEND, "Extend Map"); + } + else + { + AddMenuItem(menu, VOTE_EXTEND, "Extend Map"); + } + } +} + +GetVoteSize() +{ + new voteSize = GetConVarInt(g_Cvar_IncludeMaps); + + // New in 1.9.5 to let us bump up the included maps count + if (g_NativeVotes) + { + new max = NativeVotes_GetMaxItems(); + + if (max < voteSize) + { + voteSize = max; + } + } + + return voteSize; +} diff --git a/gameserver/addons/sourcemod/scripting/timer-maptier.sp b/gameserver/addons/sourcemod/scripting/timer-maptier.sp index 99109c0..ade0248 100644 --- a/gameserver/addons/sourcemod/scripting/timer-maptier.sp +++ b/gameserver/addons/sourcemod/scripting/timer-maptier.sp @@ -121,28 +121,23 @@ public LoadTierCallback(Handle:owner, Handle:hndl, const String:error[], any:dat Timer_LogError("SQL Error on LoadTier: %s", error); return; } - + while (SQL_FetchRow(hndl)) { new track = SQL_FetchInt(hndl, 0); g_maptier[track] = 0; g_maptier[track] = SQL_FetchInt(hndl, 1); g_stagecount[track] = SQL_FetchInt(hndl, 2); - + } + + for (new track = 0; track < MAX_TRACKS; track++) + { if (g_maptier[track] == 0) { - decl String:query[128]; - FormatEx(query, sizeof(query), "INSERT IGNORE INTO maptier (map, track, tier, stagecount) VALUES ('%s','%d','1', '1');", g_currentMap, track); - - if (g_hSQL == INVALID_HANDLE) - ConnectSQL(); - - if (g_hSQL != INVALID_HANDLE) - { - SQL_TQuery(g_hSQL, InsertTierCallback, query, track, DBPrio_Normal); - } - g_maptier[track] = 1; + decl String:query[128]; + FormatEx(query, sizeof(query), "INSERT IGNORE INTO maptier (map, track, tier, stagecount) VALUES ('%s','%d','%d', '%d');", g_currentMap, track, g_maptier[track], GetStageCount(track, false)); + SQL_TQuery(g_hSQL, InsertTierCallback, query, track, DBPrio_Normal); } } } @@ -315,29 +310,17 @@ public Native_GetMapTier(Handle:plugin, numParams) if(KvJumpToKey(hMaps, map, false)) { if(track == TRACK_NORMAL) - { tier = KvGetNum(hMaps, "tier"); - } else if(track == TRACK_BONUS) - { tier = KvGetNum(hMaps, "tier_bonus"); - } else if(track == TRACK_BONUS2) - { tier = KvGetNum(hMaps, "tier_bonus2"); - } else if(track == TRACK_BONUS3) - { tier = KvGetNum(hMaps, "tier_bonus3"); - } else if(track == TRACK_BONUS4) - { tier = KvGetNum(hMaps, "tier_bonus4"); - } else if(track == TRACK_BONUS5) - { tier = KvGetNum(hMaps, "tier_bonus5"); - } } CloseHandle(hMaps); @@ -363,38 +346,30 @@ public Native_GetMapStageCount(Handle:plugin, numParams) if(KvJumpToKey(hMaps, map, false)) { if(track == TRACK_NORMAL) - { stagecount = KvGetNum(hMaps, "stagecount"); - } else if(track == TRACK_BONUS) - { stagecount = KvGetNum(hMaps, "stagecount_bonus"); - } else if(track == TRACK_BONUS2) - { stagecount = KvGetNum(hMaps, "stagecount_bonus2"); - } else if(track == TRACK_BONUS3) - { stagecount = KvGetNum(hMaps, "stagecount_bonus3"); - } else if(track == TRACK_BONUS4) - { stagecount = KvGetNum(hMaps, "stagecount_bonus4"); - } else if(track == TRACK_BONUS5) - { stagecount = KvGetNum(hMaps, "stagecount_bonus5"); - } } CloseHandle(hMaps); - + return stagecount; } public Native_UpdateStageCount(Handle:plugin, numParams) { - new track = GetNativeCell(1); + return GetStageCount(GetNativeCell(1), true); +} + +GetStageCount(track, bool:update_sql = false) +{ if(track == TRACK_NORMAL) g_stagecount[track] = Timer_GetMapzoneCount(ZtLevel)+1; else if(track == TRACK_BONUS) @@ -407,10 +382,13 @@ public Native_UpdateStageCount(Handle:plugin, numParams) g_stagecount[track] = Timer_GetMapzoneCount(ZtBonus4Level)+1; else if(track == TRACK_BONUS5) g_stagecount[track] = Timer_GetMapzoneCount(ZtBonus5Level)+1; - - decl String:query[256]; - FormatEx(query, sizeof(query), "UPDATE maptier SET stagecount = '%d' WHERE map = '%s' AND track = '%d'", g_stagecount[track], g_currentMap, track); - SQL_TQuery(g_hSQL, UpdateStageCountCallback, query, track, DBPrio_Normal); - + + if(update_sql) + { + decl String:query[256]; + FormatEx(query, sizeof(query), "UPDATE maptier SET stagecount = '%d' WHERE map = '%s' AND track = '%d'", g_stagecount[track], g_currentMap, track); + SQL_TQuery(g_hSQL, UpdateStageCountCallback, query, track, DBPrio_Normal); + } + return g_stagecount[track]; } diff --git a/gameserver/addons/sourcemod/scripting/timer-mapzones.sp b/gameserver/addons/sourcemod/scripting/timer-mapzones.sp index 85b7336..55ca813 100644 --- a/gameserver/addons/sourcemod/scripting/timer-mapzones.sp +++ b/gameserver/addons/sourcemod/scripting/timer-mapzones.sp @@ -229,53 +229,53 @@ public OnPluginStart() HookConVarChange(g_glitch4ZoneColor, Action_OnSettingsChange); HookConVarChange(g_levelZoneColor, Action_OnSettingsChange); HookConVarChange(g_bonusLevelZoneColor, Action_OnSettingsChange); - + HookConVarChange(Sound_TeleLast, Action_OnSettingsChange); HookConVarChange(Sound_TeleNext, Action_OnSettingsChange); HookConVarChange(Sound_TimerStart, Action_OnSettingsChange); - - + + HookConVarChange(g_BeamBonusEndZonePath, Action_OnSettingsChange); HookConVarChange(g_BeamBonusStartZonePath, Action_OnSettingsChange); HookConVarChange(g_BeamDefaultPath, Action_OnSettingsChange); HookConVarChange(g_BeamEndZonePath, Action_OnSettingsChange); HookConVarChange(g_BeamStartZonePath, Action_OnSettingsChange); - + AutoExecConfig(true, "timer/timer-mapzones"); - + LoadTranslations("timer.phrases"); - + new Handle:topmenu; if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE)) { OnAdminMenuReady(topmenu); } - - RegAdminCmd("sm_zoneadminmode", Command_LevelAdminMode, ADMFLAG_RCON); - RegAdminCmd("sm_zonename", Command_LevelName, ADMFLAG_RCON); - RegAdminCmd("sm_zoneid", Command_LevelID, ADMFLAG_RCON); - RegAdminCmd("sm_zonetype", Command_LevelType, ADMFLAG_RCON); - RegAdminCmd("sm_zoneadd", Command_AddZone, ADMFLAG_RCON); - RegAdminCmd("sm_zonereload", Command_ReloadZones, ADMFLAG_SLAY); - RegAdminCmd("sm_npc_next", Command_NPC_Next, ADMFLAG_RCON); - RegAdminCmd("sm_zone", Command_AdminZone, ADMFLAG_ROOT); - RegAdminCmd("sm_zonedel", Command_AdminZoneDel, ADMFLAG_ROOT); - RegAdminCmd("sm_toggle_tp", Command_ToggleTeleporters, ADMFLAG_RCON); - + + RegAdminCmd("sm_zoneadminmode", Command_LevelAdminMode, ADMFLAG_BAN); + RegAdminCmd("sm_zonename", Command_LevelName, ADMFLAG_BAN); + RegAdminCmd("sm_zoneid", Command_LevelID, ADMFLAG_BAN); + RegAdminCmd("sm_zonetype", Command_LevelType, ADMFLAG_BAN); + RegAdminCmd("sm_zoneadd", Command_AddZone, ADMFLAG_BAN); + RegAdminCmd("sm_zonereload", Command_ReloadZones, ADMFLAG_BAN); + RegAdminCmd("sm_npc_next", Command_NPC_Next, ADMFLAG_BAN); + RegAdminCmd("sm_zone", Command_AdminZone, ADMFLAG_BAN); + RegAdminCmd("sm_zonedel", Command_AdminZoneDel, ADMFLAG_BAN); + RegAdminCmd("sm_toggle_tp", Command_ToggleTeleporters, ADMFLAG_BAN); + RegConsoleCmd("sm_levels", Command_Levels); RegConsoleCmd("sm_stage", Command_Levels); - + if(g_Settings[RestartEnable]) { RegConsoleCmd("sm_restart", Command_Restart); RegConsoleCmd("sm_r", Command_Restart); } - + if(g_Settings[StartEnable]) { RegConsoleCmd("sm_start", Command_Start); RegConsoleCmd("sm_s", Command_Start); - + RegConsoleCmd("sm_bonusrestart", Command_BonusRestart); RegConsoleCmd("sm_bonusstart", Command_BonusRestart); RegConsoleCmd("sm_br", Command_BonusRestart); @@ -290,27 +290,34 @@ public OnPluginStart() RegConsoleCmd("sm_b5", Command_Bonus5Restart); RegConsoleCmd("sm_bonus5", Command_Bonus5Restart); } - - if(g_Settings[StuckEnable]) RegConsoleCmd("sm_stuck", Command_Stuck); - + + if(g_Settings[StuckEnable]) + { + RegConsoleCmd("sm_stuck", Command_Stuck); + RegConsoleCmd("sm_resetstage", Command_Stuck); + RegConsoleCmd("sm_rs", Command_Stuck); + RegConsoleCmd("sm_gb", Command_Stuck); + RegConsoleCmd("sm_goback", Command_Stuck); + } + HookEvent("round_start", Event_RoundStart, EventHookMode_Post); HookEvent("player_spawn", Event_PlayerSpawn); - + AddNormalSoundHook(Hook_NormalSound); - + g_ioffsCollisionGroup = FindSendPropOffs("CBaseEntity", "m_CollisionGroup"); - + g_OnMapZonesLoaded = CreateGlobalForward("OnMapZonesLoaded", ET_Event); - + g_OnClientStartTouchZoneType = CreateGlobalForward("OnClientStartTouchZoneType", ET_Event, Param_Cell,Param_Cell); g_OnClientEndTouchZoneType = CreateGlobalForward("OnClientEndTouchZoneType", ET_Event, Param_Cell,Param_Cell); - + g_OnClientStartTouchLevel = CreateGlobalForward("OnClientStartTouchLevel", ET_Event, Param_Cell, Param_Cell, Param_Cell); g_OnClientStartTouchBonusLevel = CreateGlobalForward("OnClientStartTouchBonusLevel", ET_Event, Param_Cell, Param_Cell, Param_Cell); - + //Check timeleft to enforce mapchange if(g_Settings[ForceMapEndEnable]) CreateTimer(1.0, CheckRemainingTime, INVALID_HANDLE, TIMER_REPEAT); - + //Fix rotation bugs CreateTimer(300.0, Timer_FixAngRotation, _, TIMER_REPEAT); } @@ -428,23 +435,17 @@ public OnTimerStarted(client) public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon) { if(buttons & IN_USE && IsPlayerTouchingZoneType(client, ZtBlockUse)) - { buttons &= ~IN_USE; - } - + if(buttons & IN_DUCK && IsPlayerTouchingZoneType(client, ZtBlockDuck)) - { buttons &= ~IN_DUCK; - } - + if(buttons & IN_ATTACK && IsPlayerTouchingZoneType(client, ZtBlockAttack)) - { buttons &= ~IN_ATTACK; - } - + if(g_mapZoneEditors[client][Step] == 0) return Plugin_Continue; - + if (!IsPlayerAlive(client) || IsClientSourceTV(client)) return Plugin_Continue; @@ -719,12 +720,14 @@ DisplaySelectZoneTypeMenu(client, category) } else if(category == 4) { + AddMenuItem(menu, "bhop", "Allow Bhop"); AddMenuItem(menu, "auto", "Enable Auto Bhop"); AddMenuItem(menu, "noauto", "Disable Auto Bhop"); AddMenuItem(menu, "nogravity", "No Gravity verwrite"); AddMenuItem(menu, "noboost", "Disable Style Boost"); AddMenuItem(menu, "block", "Toggle Noblock"); AddMenuItem(menu, "antinoclip", "Anti Noclip"); + AddMenuItem(menu, "anticp", "Anti cPmod"); AddMenuItem(menu, "back", "Back"); } else if(category == 5) @@ -1052,7 +1055,7 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) } else if(StrEqual(info, "bonuslevel")) { - zonetype = ZtBonusCheckpoint; + zonetype = ZtBonusLevel; new String:lvlbuffer[32]; new hcount = LEVEL_BONUS_START; @@ -1083,18 +1086,18 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) hcount = g_mapZones[zone][Level_Id]; } hcount++; - + FormatEx(lvlbuffer, sizeof(lvlbuffer), "Bonus2-Checkpoint %d", hcount); - + LvlID = hcount; ZoneName = lvlbuffer; valid = true; } else if(StrEqual(info, "bonus2level")) { - zonetype = ZtBonus2Checkpoint; + zonetype = ZtBonus2Level; new String:lvlbuffer[32]; - + new hcount = LEVEL_BONUS2_START; for (new zone = 0; zone < g_mapZonesCount; zone++) { @@ -1103,9 +1106,9 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) hcount = g_mapZones[zone][Level_Id]; } hcount++; - + FormatEx(lvlbuffer, sizeof(lvlbuffer), "Bonus2-Stage %d", hcount); - + LvlID = hcount; ZoneName = lvlbuffer; valid = true; @@ -1114,7 +1117,7 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) { zonetype = ZtBonus3Checkpoint; new String:lvlbuffer[32]; - + new hcount = LEVEL_BONUS3_START; for (new zone = 0; zone < g_mapZonesCount; zone++) { @@ -1123,18 +1126,18 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) hcount = g_mapZones[zone][Level_Id]; } hcount++; - + FormatEx(lvlbuffer, sizeof(lvlbuffer), "Bonus3-Checkpoint %d", hcount); - + LvlID = hcount; ZoneName = lvlbuffer; valid = true; } else if(StrEqual(info, "bonus3level")) { - zonetype = ZtBonus3Checkpoint; + zonetype = ZtBonus3Level; new String:lvlbuffer[32]; - + new hcount = LEVEL_BONUS3_START; for (new zone = 0; zone < g_mapZonesCount; zone++) { @@ -1143,9 +1146,9 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) hcount = g_mapZones[zone][Level_Id]; } hcount++; - + FormatEx(lvlbuffer, sizeof(lvlbuffer), "Bonus3-Stage %d", hcount); - + LvlID = hcount; ZoneName = lvlbuffer; valid = true; @@ -1154,7 +1157,7 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) { zonetype = ZtBonus4Checkpoint; new String:lvlbuffer[32]; - + new hcount = LEVEL_BONUS4_START; for (new zone = 0; zone < g_mapZonesCount; zone++) { @@ -1163,18 +1166,18 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) hcount = g_mapZones[zone][Level_Id]; } hcount++; - + FormatEx(lvlbuffer, sizeof(lvlbuffer), "Bonus4-Checkpoint %d", hcount); - + LvlID = hcount; ZoneName = lvlbuffer; valid = true; } else if(StrEqual(info, "bonus4level")) { - zonetype = ZtBonus4Checkpoint; + zonetype = ZtBonus4Level; new String:lvlbuffer[32]; - + new hcount = LEVEL_BONUS4_START; for (new zone = 0; zone < g_mapZonesCount; zone++) { @@ -1183,9 +1186,9 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) hcount = g_mapZones[zone][Level_Id]; } hcount++; - + FormatEx(lvlbuffer, sizeof(lvlbuffer), "Bonus4-Stage %d", hcount); - + LvlID = hcount; ZoneName = lvlbuffer; valid = true; @@ -1194,7 +1197,7 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) { zonetype = ZtBonus5Checkpoint; new String:lvlbuffer[32]; - + new hcount = LEVEL_BONUS5_START; for (new zone = 0; zone < g_mapZonesCount; zone++) { @@ -1203,18 +1206,18 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) hcount = g_mapZones[zone][Level_Id]; } hcount++; - + FormatEx(lvlbuffer, sizeof(lvlbuffer), "Bonus5-Checkpoint %d", hcount); - + LvlID = hcount; ZoneName = lvlbuffer; valid = true; } else if(StrEqual(info, "bonus5level")) { - zonetype = ZtBonus5Checkpoint; + zonetype = ZtBonus5Level; new String:lvlbuffer[32]; - + new hcount = LEVEL_BONUS5_START; for (new zone = 0; zone < g_mapZonesCount; zone++) { @@ -1223,9 +1226,9 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) hcount = g_mapZones[zone][Level_Id]; } hcount++; - + FormatEx(lvlbuffer, sizeof(lvlbuffer), "Bonus5-Stage %d", hcount); - + LvlID = hcount; ZoneName = lvlbuffer; valid = true; @@ -1412,7 +1415,19 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) ZoneName = "Block Attack"; valid = true; } - + else if(StrEqual(info, "bhop")) + { + zonetype = ZtBhop; + ZoneName = "Allow Bhop"; + valid = true; + } + else if(StrEqual(info, "aticp")) + { + zonetype = ZtAntiCp; + ZoneName = "Anti cPmod"; + valid = true; + } + if(valid) { new Float:point1[3]; @@ -1427,14 +1442,14 @@ public ZoneTypeSelect(Handle:menu, MenuAction:action, client, itemNum) } } } - else if (action == MenuAction_End) + else if (action == MenuAction_End) { CloseHandle(menu); ResetMapZoneEditor(client); - } - else if (action == MenuAction_Cancel) + } + else if (action == MenuAction_Cancel) { - if (itemNum == MenuCancel_Exit && hTopMenu != INVALID_HANDLE) + if (itemNum == MenuCancel_Exit && hTopMenu != INVALID_HANDLE) { DisplayTopMenu(hTopMenu, client, TopMenuPosition_LastCategory); ResetMapZoneEditor(client); @@ -1446,29 +1461,29 @@ public Action:OnTouchTrigger(caller, activator) { if(!g_bZonesLoaded) return; - + if(g_mapZonesCount < 1) return; - + if (activator < 1 || activator > MaxClients) { return; } - + if (!IsClientInGame(activator)) { return; } - + if (!IsPlayerAlive(activator)) { return; } - + new client = activator; - + ChangePlayerVelocity(client); - + return; } @@ -1478,53 +1493,50 @@ public Action:StartTouchTrigger(caller, activator) return; if(g_mapZonesCount < 1) return; - + if (activator < 1 || activator > MaxClients) return; - + if (!IsClientInGame(activator)) return; - + new client = activator; - + new Float:vec[3]; GetClientAbsOrigin(client, vec); - - new mate; - if(g_timerTeams) mate = Timer_GetClientTeammate(client); - + new zone = g_MapZoneEntityZID[caller]; - + if(zone < 0) return; - - decl String:TriggerName[32]; + + decl String:TriggerName[32]; GetEntPropString(caller, Prop_Data, "m_iName", TriggerName, sizeof(TriggerName)); - + if(adminmode == 1 && Client_IsAdmin(client)) { if(GetGameMod() == MOD_CSGO) { PrintHintText(client, "ID: %d", zone); } - else + else { PrintCenterText(client, "ID: %d", zone); DrawZone(zone, false); } return; } - + Call_StartForward(g_OnClientStartTouchZoneType); Call_PushCell(client); Call_PushCell(g_mapZones[zone][Type]); Call_Finish(); - + g_bZone[zone][client] = true; - + if (!IsPlayerAlive(activator)) return; - + if (g_mapZones[zone][Type] == ZtReset) { Timer_Reset(client); @@ -1533,257 +1545,236 @@ public Action:StartTouchTrigger(caller, activator) { if(!g_Settings[NoblockEnable]) SetPush(client); - - if(mate == 0) - { - g_iIgnoreEndTouchStart[client] = false; - g_iClientLastTrackZone[client] = zone; - - Timer_Stop(client, false); - Timer_SetTrack(client, TRACK_NORMAL); - } + + g_iIgnoreEndTouchStart[client] = false; + g_iClientLastTrackZone[client] = zone; + + Timer_Stop(client, false); + Timer_SetTrack(client, TRACK_NORMAL); } else if (g_mapZones[zone][Type] == ZtBonusStart) { g_iIgnoreEndTouchStart[client] = false; g_iClientLastTrackZone[client] = zone; - + Timer_Stop(client, false); Timer_SetTrack(client, TRACK_BONUS); - + if(g_timerLjStats) SetLJMode(client, false); } else if (g_mapZones[zone][Type] == ZtBonus2Start) { g_iIgnoreEndTouchStart[client] = false; g_iClientLastTrackZone[client] = zone; - + Timer_Stop(client, false); Timer_SetTrack(client, TRACK_BONUS2); - + if(g_timerLjStats) SetLJMode(client, false); } else if (g_mapZones[zone][Type] == ZtBonus3Start) { g_iIgnoreEndTouchStart[client] = false; g_iClientLastTrackZone[client] = zone; - + Timer_Stop(client, false); Timer_SetTrack(client, TRACK_BONUS3); - + if(g_timerLjStats) SetLJMode(client, false); } else if (g_mapZones[zone][Type] == ZtBonus4Start) { g_iIgnoreEndTouchStart[client] = false; g_iClientLastTrackZone[client] = zone; - + Timer_Stop(client, false); Timer_SetTrack(client, TRACK_BONUS4); - + if(g_timerLjStats) SetLJMode(client, false); } else if (g_mapZones[zone][Type] == ZtBonus5Start) { g_iIgnoreEndTouchStart[client] = false; g_iClientLastTrackZone[client] = zone; - + Timer_Stop(client, false); Timer_SetTrack(client, TRACK_BONUS5); - + if(g_timerLjStats) SetLJMode(client, false); } else if (g_mapZones[zone][Type] == ZtEnd) { if(!g_Settings[NoblockEnable]) SetPush(client); - - if(mate == 0) + + //has player noclip? + if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) { - //has player noclip? - if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) - { - Timer_Stop(client, false); - } - else if(Timer_GetTrack(client) == TRACK_NORMAL) + Timer_Stop(client, false); + } + else if(Timer_GetTrack(client) == TRACK_NORMAL) + { + g_iClientLastTrackZone[client] = zone; + + if (Timer_Stop(client, false)) { - g_iClientLastTrackZone[client] = zone; - - if (Timer_Stop(client, false)) + new bool:enabled = false; + new jumps = 0; + new Float:time; + new fpsmax; + + if (Timer_GetClientTimer(client, enabled, time, jumps, fpsmax)) { - new bool:enabled = false; - new jumps = 0; - new Float:time; - new fpsmax; - - if (Timer_GetClientTimer(client, enabled, time, jumps, fpsmax)) - { - new difficulty = 0; - if (g_timerPhysics) - difficulty = Timer_GetStyle(client); - - Timer_FinishRound(client, g_currentMap, time, jumps, difficulty, fpsmax, TRACK_NORMAL); - } + new difficulty = 0; + if (g_timerPhysics) + difficulty = Timer_GetStyle(client); + + Timer_FinishRound(client, g_currentMap, time, jumps, difficulty, fpsmax, TRACK_NORMAL); } } } } else if (g_mapZones[zone][Type] == ZtBonusEnd) { - if(mate == 0) + //has player noclip? + if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) { - //has player noclip? - if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) - { - Timer_Stop(client, false); - } - else if(Timer_GetTrack(client) == TRACK_BONUS) + Timer_Stop(client, false); + } + else if(Timer_GetTrack(client) == TRACK_BONUS) + { + g_iClientLastTrackZone[client] = zone; + + if (Timer_Stop(client, false)) { - g_iClientLastTrackZone[client] = zone; - - if (Timer_Stop(client, false)) + new bool:enabled = false; + new jumps = 0; + new Float:time; + new fpsmax; + + if (Timer_GetClientTimer(client, enabled, time, jumps, fpsmax)) { - new bool:enabled = false; - new jumps = 0; - new Float:time; - new fpsmax; - - if (Timer_GetClientTimer(client, enabled, time, jumps, fpsmax)) - { - new difficulty = 0; - if (g_timerPhysics) - difficulty = Timer_GetStyle(client); - - Timer_FinishRound(client, g_currentMap, time, jumps, difficulty, fpsmax, TRACK_BONUS); - } + new difficulty = 0; + if (g_timerPhysics) + difficulty = Timer_GetStyle(client); + + Timer_FinishRound(client, g_currentMap, time, jumps, difficulty, fpsmax, TRACK_BONUS); } } } } else if (g_mapZones[zone][Type] == ZtBonus2End) { - if(mate == 0) + //has player noclip? + if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) { - //has player noclip? - if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) - { - Timer_Stop(client, false); - } - else if(Timer_GetTrack(client) == TRACK_BONUS2) + Timer_Stop(client, false); + } + else if(Timer_GetTrack(client) == TRACK_BONUS2) + { + g_iClientLastTrackZone[client] = zone; + + if (Timer_Stop(client, false)) { - g_iClientLastTrackZone[client] = zone; - - if (Timer_Stop(client, false)) + new bool:enabled = false; + new jumps = 0; + new Float:time; + new fpsmax; + + if (Timer_GetClientTimer(client, enabled, time, jumps, fpsmax)) { - new bool:enabled = false; - new jumps = 0; - new Float:time; - new fpsmax; - - if (Timer_GetClientTimer(client, enabled, time, jumps, fpsmax)) - { - new difficulty = 0; - if (g_timerPhysics) - difficulty = Timer_GetStyle(client); - - Timer_FinishRound(client, g_currentMap, time, jumps, difficulty, fpsmax, TRACK_BONUS2); - } + new difficulty = 0; + if (g_timerPhysics) + difficulty = Timer_GetStyle(client); + + Timer_FinishRound(client, g_currentMap, time, jumps, difficulty, fpsmax, TRACK_BONUS2); } } } } else if (g_mapZones[zone][Type] == ZtBonus3End) { - if(mate == 0) + //has player noclip? + if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) { - //has player noclip? - if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) - { - Timer_Stop(client, false); - } - else if(Timer_GetTrack(client) == TRACK_BONUS3) + Timer_Stop(client, false); + } + else if(Timer_GetTrack(client) == TRACK_BONUS3) + { + g_iClientLastTrackZone[client] = zone; + + if (Timer_Stop(client, false)) { - g_iClientLastTrackZone[client] = zone; - - if (Timer_Stop(client, false)) + new bool:enabled = false; + new jumps = 0; + new Float:time; + new fpsmax; + + if (Timer_GetClientTimer(client, enabled, time, jumps, fpsmax)) { - new bool:enabled = false; - new jumps = 0; - new Float:time; - new fpsmax; - - if (Timer_GetClientTimer(client, enabled, time, jumps, fpsmax)) - { - new difficulty = 0; - if (g_timerPhysics) - difficulty = Timer_GetStyle(client); - - Timer_FinishRound(client, g_currentMap, time, jumps, difficulty, fpsmax, TRACK_BONUS3); - } + new difficulty = 0; + if (g_timerPhysics) + difficulty = Timer_GetStyle(client); + + Timer_FinishRound(client, g_currentMap, time, jumps, difficulty, fpsmax, TRACK_BONUS3); } } } } else if (g_mapZones[zone][Type] == ZtBonus4End) { - if(mate == 0) + //has player noclip? + if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) { - //has player noclip? - if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) - { - Timer_Stop(client, false); - } - else if(Timer_GetTrack(client) == TRACK_BONUS4) - { - g_iClientLastTrackZone[client] = zone; - - if (Timer_Stop(client, false)) + Timer_Stop(client, false); + } + else if(Timer_GetTrack(client) == TRACK_BONUS4) + { + g_iClientLastTrackZone[client] = zone; + + if (Timer_Stop(client, false)) + { + new bool:enabled = false; + new jumps = 0; + new Float:time; + new fpsmax; + + if (Timer_GetClientTimer(client, enabled, time, jumps, fpsmax)) { - new bool:enabled = false; - new jumps = 0; - new Float:time; - new fpsmax; - - if (Timer_GetClientTimer(client, enabled, time, jumps, fpsmax)) - { - new difficulty = 0; - if (g_timerPhysics) - difficulty = Timer_GetStyle(client); - - Timer_FinishRound(client, g_currentMap, time, jumps, difficulty, fpsmax, TRACK_BONUS4); - } + new difficulty = 0; + if (g_timerPhysics) + difficulty = Timer_GetStyle(client); + + Timer_FinishRound(client, g_currentMap, time, jumps, difficulty, fpsmax, TRACK_BONUS4); } } } } else if (g_mapZones[zone][Type] == ZtBonus5End) { - if(mate == 0) + //has player noclip? + if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) { - //has player noclip? - if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) - { - Timer_Stop(client, false); - } - else if(Timer_GetTrack(client) == TRACK_BONUS5) + Timer_Stop(client, false); + } + else if(Timer_GetTrack(client) == TRACK_BONUS5) + { + g_iClientLastTrackZone[client] = zone; + + if (Timer_Stop(client, false)) { - g_iClientLastTrackZone[client] = zone; - - if (Timer_Stop(client, false)) + new bool:enabled = false; + new jumps = 0; + new Float:time; + new fpsmax; + + if (Timer_GetClientTimer(client, enabled, time, jumps, fpsmax)) { - new bool:enabled = false; - new jumps = 0; - new Float:time; - new fpsmax; - - if (Timer_GetClientTimer(client, enabled, time, jumps, fpsmax)) - { - new difficulty = 0; - if (g_timerPhysics) - difficulty = Timer_GetStyle(client); - - Timer_FinishRound(client, g_currentMap, time, jumps, difficulty, fpsmax, TRACK_BONUS5); - } + new difficulty = 0; + if (g_timerPhysics) + difficulty = Timer_GetStyle(client); + + Timer_FinishRound(client, g_currentMap, time, jumps, difficulty, fpsmax, TRACK_BONUS5); } } } @@ -1794,23 +1785,23 @@ public Action:StartTouchTrigger(caller, activator) } else if (g_mapZones[zone][Type] == ZtRestart) { - if(Timer_GetTrack(client) == TRACK_BONUS) + if(Timer_GetTrack(client) == TRACK_BONUS) { Tele_Level(client, LEVEL_BONUS_START); } - else if(Timer_GetTrack(client) == TRACK_BONUS2) + else if(Timer_GetTrack(client) == TRACK_BONUS2) { Tele_Level(client, LEVEL_BONUS2_START); } - else if(Timer_GetTrack(client) == TRACK_BONUS3) + else if(Timer_GetTrack(client) == TRACK_BONUS3) { Tele_Level(client, LEVEL_BONUS3_START); } - else if(Timer_GetTrack(client) == TRACK_BONUS4) + else if(Timer_GetTrack(client) == TRACK_BONUS4) { Tele_Level(client, LEVEL_BONUS4_START); } - else if(Timer_GetTrack(client) == TRACK_BONUS5) + else if(Timer_GetTrack(client) == TRACK_BONUS5) { Tele_Level(client, LEVEL_BONUS5_START); } @@ -1821,30 +1812,30 @@ public Action:StartTouchTrigger(caller, activator) } else if (g_mapZones[zone][Type] == ZtRestartNormalTimer) { - if(Timer_GetTrack(client) == TRACK_NORMAL) + if(Timer_GetTrack(client) == TRACK_NORMAL) { Tele_Level(client, LEVEL_START); } } else if (g_mapZones[zone][Type] == ZtRestartBonusTimer) { - if(Timer_GetTrack(client) == TRACK_BONUS) + if(Timer_GetTrack(client) == TRACK_BONUS) { Tele_Level(client, LEVEL_BONUS_START); } - else if(Timer_GetTrack(client) == TRACK_BONUS2) + else if(Timer_GetTrack(client) == TRACK_BONUS2) { Tele_Level(client, LEVEL_BONUS2_START); } - else if(Timer_GetTrack(client) == TRACK_BONUS3) + else if(Timer_GetTrack(client) == TRACK_BONUS3) { Tele_Level(client, LEVEL_BONUS3_START); } - else if(Timer_GetTrack(client) == TRACK_BONUS4) + else if(Timer_GetTrack(client) == TRACK_BONUS4) { Tele_Level(client, LEVEL_BONUS4_START); } - else if(Timer_GetTrack(client) == TRACK_BONUS5) + else if(Timer_GetTrack(client) == TRACK_BONUS5) { Tele_Level(client, LEVEL_BONUS5_START); } @@ -1852,38 +1843,18 @@ public Action:StartTouchTrigger(caller, activator) else if (g_mapZones[zone][Type] == ZtLast) { new lowestcheckpoint = g_mapZones[g_iClientLastTrackZone[client]][Level_Id]; - - if(0 < mate && IsClientInGame(mate) && IsPlayerAlive(mate)) - { - if(g_iClientLastTrackZone[client] > g_iClientLastTrackZone[mate]) lowestcheckpoint = g_mapZones[g_iClientLastTrackZone[mate]][Level_Id]; - - Tele_Level(client, lowestcheckpoint); - Tele_Level(mate, lowestcheckpoint); - - if(Client_IsValid(client, true)) EmitSoundToClient(client, SND_TELE_LAST); - if(Client_IsValid(mate, true)) EmitSoundToClient(mate, SND_TELE_LAST); - } - else - { - if(Client_IsValid(client, true)) EmitSoundToClient(client, SND_TELE_LAST); - Tele_Level(client, lowestcheckpoint); - } + Tele_Level(client, lowestcheckpoint); + + if(Client_IsValid(client, true)) + EmitSoundToClient(client, SND_TELE_LAST); } else if (g_mapZones[zone][Type] == ZtNext) { - if(0 < mate && IsClientInGame(mate) && IsPlayerAlive(mate) && g_mapZones[g_iClientLastTrackZone[client]][Level_Id] == g_mapZones[g_iClientLastTrackZone[mate]][Level_Id]) - { - Tele_Level(client, g_mapZones[g_iClientLastTrackZone[client]][Level_Id]+1); - Tele_Level(mate, g_mapZones[g_iClientLastTrackZone[client]][Level_Id]+1); - if(Client_IsValid(client, true)) EmitSoundToClient(client, SND_TELE_NEXT); - if(Client_IsValid(mate, true)) EmitSoundToClient(mate, SND_TELE_NEXT); - } - else - { - Tele_Level(client, g_mapZones[g_iClientLastTrackZone[client]][Level_Id]+1); - if(Client_IsValid(client, true)) EmitSoundToClient(client, SND_TELE_NEXT); - } - + Tele_Level(client, g_mapZones[g_iClientLastTrackZone[client]][Level_Id]+1); + + if(Client_IsValid(client, true)) + EmitSoundToClient(client, SND_TELE_NEXT); + } else if (g_mapZones[zone][Type] == ZtLevel) { @@ -1891,7 +1862,7 @@ public Action:StartTouchTrigger(caller, activator) { new lastlevel = g_mapZones[g_iClientLastTrackZone[client]][Level_Id]; g_iClientLastTrackZone[client] = zone; - + Call_StartForward(g_OnClientStartTouchLevel); Call_PushCell(client); Call_PushCell(g_mapZones[g_iClientLastTrackZone[client]][Level_Id]); @@ -1905,7 +1876,7 @@ public Action:StartTouchTrigger(caller, activator) { new lastlevel = g_mapZones[g_iClientLastTrackZone[client]][Level_Id]; g_iClientLastTrackZone[client] = zone; - + Call_StartForward(g_OnClientStartTouchLevel); Call_PushCell(client); Call_PushCell(g_mapZones[g_iClientLastTrackZone[client]][Level_Id]); @@ -1919,7 +1890,7 @@ public Action:StartTouchTrigger(caller, activator) { new lastlevel = g_mapZones[g_iClientLastTrackZone[client]][Level_Id]; g_iClientLastTrackZone[client] = zone; - + Call_StartForward(g_OnClientStartTouchBonusLevel); Call_PushCell(client); Call_PushCell(g_mapZones[g_iClientLastTrackZone[client]][Level_Id]); @@ -1933,7 +1904,7 @@ public Action:StartTouchTrigger(caller, activator) { new lastlevel = g_mapZones[g_iClientLastTrackZone[client]][Level_Id]; g_iClientLastTrackZone[client] = zone; - + Call_StartForward(g_OnClientStartTouchBonusLevel); Call_PushCell(client); Call_PushCell(g_mapZones[g_iClientLastTrackZone[client]][Level_Id]); @@ -1947,7 +1918,7 @@ public Action:StartTouchTrigger(caller, activator) { new lastlevel = g_mapZones[g_iClientLastTrackZone[client]][Level_Id]; g_iClientLastTrackZone[client] = zone; - + Call_StartForward(g_OnClientStartTouchBonusLevel); Call_PushCell(client); Call_PushCell(g_mapZones[g_iClientLastTrackZone[client]][Level_Id]); @@ -1961,7 +1932,7 @@ public Action:StartTouchTrigger(caller, activator) { new lastlevel = g_mapZones[g_iClientLastTrackZone[client]][Level_Id]; g_iClientLastTrackZone[client] = zone; - + Call_StartForward(g_OnClientStartTouchBonusLevel); Call_PushCell(client); Call_PushCell(g_mapZones[g_iClientLastTrackZone[client]][Level_Id]); @@ -1975,7 +1946,7 @@ public Action:StartTouchTrigger(caller, activator) { new lastlevel = g_mapZones[g_iClientLastTrackZone[client]][Level_Id]; g_iClientLastTrackZone[client] = zone; - + Call_StartForward(g_OnClientStartTouchBonusLevel); Call_PushCell(client); Call_PushCell(g_mapZones[g_iClientLastTrackZone[client]][Level_Id]); @@ -1989,7 +1960,7 @@ public Action:StartTouchTrigger(caller, activator) { new lastlevel = g_mapZones[g_iClientLastTrackZone[client]][Level_Id]; g_iClientLastTrackZone[client] = zone; - + Call_StartForward(g_OnClientStartTouchBonusLevel); Call_PushCell(client); Call_PushCell(g_mapZones[g_iClientLastTrackZone[client]][Level_Id]); @@ -2003,7 +1974,7 @@ public Action:StartTouchTrigger(caller, activator) { new lastlevel = g_mapZones[g_iClientLastTrackZone[client]][Level_Id]; g_iClientLastTrackZone[client] = zone; - + Call_StartForward(g_OnClientStartTouchBonusLevel); Call_PushCell(client); Call_PushCell(g_mapZones[g_iClientLastTrackZone[client]][Level_Id]); @@ -2017,7 +1988,7 @@ public Action:StartTouchTrigger(caller, activator) { new lastlevel = g_mapZones[g_iClientLastTrackZone[client]][Level_Id]; g_iClientLastTrackZone[client] = zone; - + Call_StartForward(g_OnClientStartTouchBonusLevel); Call_PushCell(client); Call_PushCell(g_mapZones[g_iClientLastTrackZone[client]][Level_Id]); @@ -2031,7 +2002,7 @@ public Action:StartTouchTrigger(caller, activator) { new lastlevel = g_mapZones[g_iClientLastTrackZone[client]][Level_Id]; g_iClientLastTrackZone[client] = zone; - + Call_StartForward(g_OnClientStartTouchBonusLevel); Call_PushCell(client); Call_PushCell(g_mapZones[g_iClientLastTrackZone[client]][Level_Id]); @@ -2045,7 +2016,7 @@ public Action:StartTouchTrigger(caller, activator) { new lastlevel = g_mapZones[g_iClientLastTrackZone[client]][Level_Id]; g_iClientLastTrackZone[client] = zone; - + Call_StartForward(g_OnClientStartTouchBonusLevel); Call_PushCell(client); Call_PushCell(g_mapZones[g_iClientLastTrackZone[client]][Level_Id]); @@ -2075,7 +2046,7 @@ public Action:StartTouchTrigger(caller, activator) { SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", 0.7); } - + return; } @@ -2083,32 +2054,29 @@ public Action:EndTouchTrigger(caller, activator) { if(!g_bZonesLoaded) return; - + if(g_mapZonesCount < 1) return; - + if (activator < 1 || activator > MaxClients) return; - + if (!IsClientInGame(activator)) return; - + new client = activator; - + new Float:vec[3]; GetClientAbsOrigin(client, vec); - - new mate; - if(g_timerTeams) mate = Timer_GetClientTeammate(client); - + new zone = g_MapZoneEntityZID[caller]; - + if(zone < 0) return; - - decl String:TriggerName[32]; + + decl String:TriggerName[32]; GetEntPropString(caller, Prop_Data, "m_iName", TriggerName, sizeof(TriggerName)); - + if(adminmode == 1 && Client_IsAdmin(client)) { if(GetGameMod() == MOD_CSGO) @@ -2118,26 +2086,26 @@ public Action:EndTouchTrigger(caller, activator) else PrintCenterText(client, "ID: %d", zone); return; } - + Call_StartForward(g_OnClientEndTouchZoneType); Call_PushCell(client); Call_PushCell(g_mapZones[zone][Type]); Call_Finish(); - + g_bZone[zone][client] = false; - + if (!IsPlayerAlive(activator)) return; - + if(Timer_GetForceStyle() && !Timer_GetPickedStyle(client)) { if(GetGameTime()-g_fSpawnTime[client] > 0.5) Tele_Level(client, LEVEL_START); - + FakeClientCommand(client, "sm_style"); CPrintToChat(client, PLUGIN_PREFIX, "Force Mode"); } - + if(g_mapZones[zone][Type] == ZtEnd) { if(!g_Settings[NoblockEnable]) @@ -2147,24 +2115,24 @@ public Action:EndTouchTrigger(caller, activator) { if(!g_Settings[NoblockEnable]) SetBlock(client); - - if(mate == 0 && CheckIllegalTeleport(client)) + + if(CheckIllegalTeleport(client)) { if(Timer_IsPlayerTouchingZoneType(client, ZtStop)) return; - + if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) return; - + if(g_iIgnoreEndTouchStart[client]) { g_iIgnoreEndTouchStart[client] = false; return; } - + if(IsClientConnected(client)) EmitSoundToClient(client, SND_TIMER_START); - + Timer_Restart(client); Timer_SetTrack(client, TRACK_NORMAL); } @@ -2173,16 +2141,19 @@ public Action:EndTouchTrigger(caller, activator) { if(Timer_IsPlayerTouchingZoneType(client, ZtStop) || !CheckIllegalTeleport(client)) return; - + if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) return; - + if(g_iIgnoreEndTouchStart[client]) { g_iIgnoreEndTouchStart[client] = false; return; } - if(IsClientConnected(client)) EmitSoundToClient(client, SND_TIMER_START); + + if(IsClientConnected(client)) + EmitSoundToClient(client, SND_TIMER_START); + Timer_Restart(client); Timer_SetTrack(client, TRACK_BONUS); } @@ -2190,16 +2161,19 @@ public Action:EndTouchTrigger(caller, activator) { if(Timer_IsPlayerTouchingZoneType(client, ZtStop) || !CheckIllegalTeleport(client)) return; - + if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) return; - + if(g_iIgnoreEndTouchStart[client]) { g_iIgnoreEndTouchStart[client] = false; return; } - if(IsClientConnected(client)) EmitSoundToClient(client, SND_TIMER_START); + + if(IsClientConnected(client)) + EmitSoundToClient(client, SND_TIMER_START); + Timer_Restart(client); Timer_SetTrack(client, TRACK_BONUS2); } @@ -2207,16 +2181,19 @@ public Action:EndTouchTrigger(caller, activator) { if(Timer_IsPlayerTouchingZoneType(client, ZtStop) || !CheckIllegalTeleport(client)) return; - + if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) return; - + if(g_iIgnoreEndTouchStart[client]) { g_iIgnoreEndTouchStart[client] = false; return; } - if(IsClientConnected(client)) EmitSoundToClient(client, SND_TIMER_START); + + if(IsClientConnected(client)) + EmitSoundToClient(client, SND_TIMER_START); + Timer_Restart(client); Timer_SetTrack(client, TRACK_BONUS3); } @@ -2224,16 +2201,19 @@ public Action:EndTouchTrigger(caller, activator) { if(Timer_IsPlayerTouchingZoneType(client, ZtStop) || !CheckIllegalTeleport(client)) return; - + if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) return; - + if(g_iIgnoreEndTouchStart[client]) { g_iIgnoreEndTouchStart[client] = false; return; } - if(IsClientConnected(client)) EmitSoundToClient(client, SND_TIMER_START); + + if(IsClientConnected(client)) + EmitSoundToClient(client, SND_TIMER_START); + Timer_Restart(client); Timer_SetTrack(client, TRACK_BONUS4); } @@ -2241,16 +2221,19 @@ public Action:EndTouchTrigger(caller, activator) { if(Timer_IsPlayerTouchingZoneType(client, ZtStop) || !CheckIllegalTeleport(client)) return; - + if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) return; - + if(g_iIgnoreEndTouchStart[client]) { g_iIgnoreEndTouchStart[client] = false; return; } - if(IsClientConnected(client)) EmitSoundToClient(client, SND_TIMER_START); + + if(IsClientConnected(client)) + EmitSoundToClient(client, SND_TIMER_START); + Timer_Restart(client); Timer_SetTrack(client, TRACK_BONUS5); } @@ -2272,40 +2255,40 @@ public Action:EndTouchTrigger(caller, activator) { SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", 1.0); } - + return; -} +} public Action:NPC_Use(caller, activator) { decl Float:camangle[3], Float:vecClient[3], Float:vecCaller[3]; - + decl Float:vec[3]; Entity_GetAbsOrigin(caller, vecCaller); - GetClientAbsOrigin(activator, vecClient); - + GetClientAbsOrigin(activator, vecClient); + MakeVectorFromPoints(vecCaller, vecClient, vec); GetVectorAngles(vec, camangle); camangle[0] = 0.0; camangle[2] = 0.0; - + TeleportEntity(caller, NULL_VECTOR, camangle, NULL_VECTOR); - + for (new i = 0; i < g_mapZonesCount; i++) { if(g_mapZones[i][NPC] == caller) { g_iClientLastTrackZone[activator] = i; - + Menu_NPC_Next(activator, i); - + break; } } - + SetEntData(caller, g_ioffsCollisionGroup, 17, 4, true); CreateTimer(0.5, SetBlockable, caller, TIMER_FLAG_NO_MAPCHANGE); - + return Plugin_Continue; } @@ -2313,16 +2296,16 @@ public OnConfigsExecuted() { //Sounds CacheSounds(); - + //Sprites GetConVarString(g_BeamDefaultPath, g_sBeamDefaultPath, sizeof(g_sBeamDefaultPath)); GetConVarString(g_BeamStartZonePath, g_sBeamStartZonePath, sizeof(g_sBeamStartZonePath)); GetConVarString(g_BeamEndZonePath, g_sBeamEndZonePath, sizeof(g_sBeamEndZonePath)); GetConVarString(g_BeamBonusStartZonePath, g_sBeamBonusStartZonePath, sizeof(g_sBeamBonusStartZonePath)); GetConVarString(g_BeamBonusEndZonePath, g_sBeamBonusEndZonePath, sizeof(g_sBeamBonusEndZonePath)); - + InitZoneSprites(); - + //Colors new String:buffer[128]; GetConVarString(g_startMapZoneColor, buffer, sizeof(buffer)); @@ -2353,10 +2336,10 @@ CacheSounds() { GetConVarString(Sound_TeleLast, SND_TELE_LAST, sizeof(SND_TELE_LAST)); PrepareSound(SND_TELE_LAST); - + GetConVarString(Sound_TeleNext, SND_TELE_NEXT, sizeof(SND_TELE_NEXT)); PrepareSound(SND_TELE_NEXT); - + GetConVarString(Sound_TimerStart, SND_TIMER_START, sizeof(SND_TIMER_START)); PrepareSound(SND_TIMER_START); } @@ -2364,9 +2347,9 @@ CacheSounds() public PrepareSound(String: sound[MAX_FILE_LEN]) { decl String:fileSound[MAX_FILE_LEN]; - + FormatEx(fileSound, MAX_FILE_LEN, "sound/%s", sound); - + if (FileExists(fileSound)) { PrecacheSound(sound, true); @@ -2381,7 +2364,7 @@ public PrepareSound(String: sound[MAX_FILE_LEN]) InitZoneSprites() { new String:spritebuffer[256]; - + //default sprite GetConVarString(g_BeamDefaultPath, g_sBeamDefaultPath, sizeof(g_sBeamDefaultPath)); Format(spritebuffer, sizeof(spritebuffer), "%s.vmt", g_sBeamDefaultPath); @@ -2392,7 +2375,7 @@ InitZoneSprites() Format(spritebuffer, sizeof(spritebuffer), "%s.vtf", g_sBeamDefaultPath); AddFileToDownloadsTable(spritebuffer); } - + //start sprite GetConVarString(g_BeamStartZonePath, g_sBeamStartZonePath, sizeof(g_sBeamStartZonePath)); Format(spritebuffer, sizeof(spritebuffer), "%s.vmt", g_sBeamStartZonePath); @@ -2403,7 +2386,7 @@ InitZoneSprites() Format(spritebuffer, sizeof(spritebuffer), "%s.vtf", g_sBeamStartZonePath); AddFileToDownloadsTable(spritebuffer); } - + //end sprite GetConVarString(g_BeamEndZonePath, g_sBeamEndZonePath, sizeof(g_sBeamEndZonePath)); Format(spritebuffer, sizeof(spritebuffer), "%s.vmt", g_sBeamEndZonePath); @@ -2414,7 +2397,7 @@ InitZoneSprites() Format(spritebuffer, sizeof(spritebuffer), "%s.vtf", g_sBeamEndZonePath); AddFileToDownloadsTable(spritebuffer); } - + //bonus start sprite GetConVarString(g_BeamBonusStartZonePath, g_sBeamBonusStartZonePath, sizeof(g_sBeamBonusStartZonePath)); Format(spritebuffer, sizeof(spritebuffer), "%s.vmt", g_sBeamBonusStartZonePath); @@ -2425,7 +2408,7 @@ InitZoneSprites() Format(spritebuffer, sizeof(spritebuffer), "%s.vtf", g_sBeamBonusStartZonePath); AddFileToDownloadsTable(spritebuffer); } - + //bonus end sprite GetConVarString(g_BeamBonusEndZonePath, g_sBeamBonusEndZonePath, sizeof(g_sBeamBonusEndZonePath)); Format(spritebuffer, sizeof(spritebuffer), "%s.vmt", g_sBeamBonusEndZonePath); @@ -2444,16 +2427,16 @@ public Action:CheckEntitysLoaded(Handle:timer) { if (g_hSQL == INVALID_HANDLE) ConnectSQL(); - + if (g_hSQL != INVALID_HANDLE) { Timer_LogInfo("No mapzone entitys spawned, reloading..."); LoadMapZones(); } - + CreateTimer(4.0, CheckEntitysLoaded, _, TIMER_FLAG_NO_MAPCHANGE); } - + return Plugin_Stop; } @@ -2468,65 +2451,40 @@ public OnClientDisconnect_Post(client) //Credits to 1NutWunDeR public Action:CheckRemainingTime(Handle:timer) { - new Handle:hTmp; + new Handle:hTmp; hTmp = FindConVar("mp_timelimit"); - new iTimeLimit = GetConVarInt(hTmp); + new iTimeLimit = GetConVarInt(hTmp); if (hTmp != INVALID_HANDLE) - CloseHandle(hTmp); + CloseHandle(hTmp); if (iTimeLimit > 0) { new timeleft; GetMapTimeLeft(timeleft); - + new tier; if(g_timerMapTier) tier = Timer_GetTier(TRACK_NORMAL); - + decl String:sTier[32]; - Format(sTier, sizeof(sTier), " Map Tier: %d", tier); - - if(GetEngineVersion() == Engine_CSGO) - { - switch(timeleft) - { - case 1800: CPrintToChatAll("Current Map: %s%s Time Remaining: 30 minutes", g_currentMap, sTier); - case 1200: CPrintToChatAll("Current Map: %s%s Time Remaining: 20 minutes", g_currentMap, sTier); - case 600: CPrintToChatAll("Current Map: %s%s Time Remaining: 10 minutes", g_currentMap, sTier); - case 300: CPrintToChatAll("Current Map: %s%s Time Remaining: 5 minutes", g_currentMap, sTier); - case 120: CPrintToChatAll("Current Map: %s%s Time Remaining: 2 minutes", g_currentMap, sTier); - case 60: CPrintToChatAll("Current Map: %s%s Time Remaining: 60 seconds", g_currentMap, sTier); - case 30: CPrintToChatAll("Current Map: %s%s Time Remaining: 30 seconds", g_currentMap, sTier); - case 15: CPrintToChatAll("Current Map: %s%s Time Remaining: 15 seconds", g_currentMap, sTier); - case -1: CPrintToChatAll("3.."); - case -2: CPrintToChatAll("2.."); - case -3: - { - CPrintToChatAll("1.."); - CreateTimer(1.0, TerminateRoundTimer, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE); - } - } - } - else + Format(sTier, sizeof(sTier), " Tier: %d", tier); + + switch(timeleft) { - switch(timeleft) - { - case 1800: CPrintToChatAll("Current Map: %s%s Time Remaining: 30 minutes", g_currentMap, sTier); - case 1200: CPrintToChatAll("Current Map: %s%s Time Remaining: 20 minutes", g_currentMap, sTier); - case 600: CPrintToChatAll("Current Map: %s%s Time Remaining: 10 minutes", g_currentMap, sTier); - case 300: CPrintToChatAll("Current Map: %s%s Time Remaining: 5 minutes", g_currentMap, sTier); - case 120: CPrintToChatAll("Current Map: %s%s Time Remaining: 2 minutes", g_currentMap, sTier); - case 60: CPrintToChatAll("Current Map: %s%s Time Remaining: 60 seconds", g_currentMap, sTier); - case 30: CPrintToChatAll("Current Map: %s%s Time Remaining: 30 seconds", g_currentMap, sTier); - case 15: CPrintToChatAll("Current Map: %s%s Time Remaining: 15 seconds", g_currentMap, sTier); - case -1: CPrintToChatAll("3.."); - case -2: CPrintToChatAll("2.."); - case -3: - { - CPrintToChatAll("1.."); - CreateTimer(1.0, TerminateRoundTimer, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE); - } - } + case 1800: CPrintToChatAll("Current Map: %s%s Time Remaining: 30 minutes", g_currentMap, sTier); + case 1200: CPrintToChatAll("Current Map: %s%s Time Remaining: 20 minutes", g_currentMap, sTier); + case 600: CPrintToChatAll("Current Map: %s%s Time Remaining: 10 minutes", g_currentMap, sTier); + case 300: CPrintToChatAll("Current Map: %s%s Time Remaining: 5 minutes", g_currentMap, sTier); + case 120: CPrintToChatAll("Current Map: %s%s Time Remaining: 2 minutes", g_currentMap, sTier); + case 60: CPrintToChatAll("Current Map: %s%s Time Remaining: 60 seconds", g_currentMap, sTier); + case 30: CPrintToChatAll("Current Map: %s%s Time Remaining: 30 seconds", g_currentMap, sTier); + case 15: CPrintToChatAll("Current Map: %s%s Time Remaining: 15 seconds", g_currentMap, sTier); + case -1: CPrintToChatAll("3.."); + case -2: CPrintToChatAll("2.."); + case -3: CPrintToChatAll("1.."); } + + if(timeleft < -3 && !g_bAllowRoundEnd) + CreateTimer(0.0, TerminateRoundTimer, INVALID_HANDLE, TIMER_FLAG_NO_MAPCHANGE); } } @@ -2550,11 +2508,11 @@ public Action:CS_OnTerminateRound(&Float:delay, &CSRoundEndReason:reason) g_bAllowRoundEnd = false; return Plugin_Continue; } - + // Block round end if(g_Settings[TerminateRoundEnd]) return Plugin_Handled; - + // Let the round end return Plugin_Continue; } @@ -2563,10 +2521,10 @@ public Action:Event_RoundStart(Handle:event,const String:name[],bool:dontBroadca { if (g_hSQL == INVALID_HANDLE) ConnectSQL(); - + if (g_hSQL != INVALID_HANDLE) LoadMapZones(); - + else CreateTimer(3.0, Timer_LoadMapzones, _ , TIMER_FLAG_NO_MAPCHANGE); } @@ -2574,44 +2532,44 @@ public Action:Timer_LoadMapzones(Handle:timer, any:data) { if (g_hSQL == INVALID_HANDLE) ConnectSQL(); - + if (g_hSQL != INVALID_HANDLE) LoadMapZones(); - + else CreateTimer(3.0, Timer_LoadMapzones, _ , TIMER_FLAG_NO_MAPCHANGE); - + return Plugin_Stop; } public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) { new client = GetClientOfUserId(GetEventInt(event, "userid")); - + g_iClientLastTrackZone[client] = 0; g_iIgnoreEndTouchStart[client] = 0; g_iTargetNPC[client] = 0; Timer_Resume(client); Timer_Stop(client, false); - + for (new i = 0; i <= 127; i++) { g_bZone[i][client] = false; } - + if(g_Settings[TeleportOnSpawn]) { // Prevent infinite loop if(GetGameTime()-g_fSpawnTime[client] > 0.5) Tele_Level(client, LEVEL_START); } - + if(IsClientInGame(client) && IsPlayerAlive(client)) { if(g_Settings[NoblockEnable]) SetNoBlock(client); else SetBlock(client); } - + g_fSpawnTime[client] = GetGameTime(); } @@ -2690,11 +2648,11 @@ bool:AddMapZone(String:map[], MapZoneType:type, String:name[], level_id, Float:p { if (g_hSQL == INVALID_HANDLE) ConnectSQL(); - + if (g_hSQL != INVALID_HANDLE) { decl String:query[512]; - + if ((type == ZtStart && !g_Settings[AllowMultipleStart]) || (type == ZtEnd && !g_Settings[AllowMultipleEnd]) || (type == ZtBonusStart && !g_Settings[AllowMultipleBonusStart]) @@ -2702,18 +2660,18 @@ bool:AddMapZone(String:map[], MapZoneType:type, String:name[], level_id, Float:p { decl String:deleteQuery[256]; FormatEx(deleteQuery, sizeof(deleteQuery), "DELETE FROM mapzone WHERE map = '%s' AND type = %d;", map, type); - - SQL_TQuery(g_hSQL, MapZoneChangedCallback, deleteQuery, _, DBPrio_High); + + SQL_TQuery(g_hSQL, MapZoneChangedCallback, deleteQuery, _, DBPrio_High); } - + //add new zone FormatEx(query, sizeof(query), "INSERT INTO mapzone (map, type, name, level_id, point1_x, point1_y, point1_z, point2_x, point2_y, point2_z) VALUES ('%s','%d','%s','%d', %f, %f, %f, %f, %f, %f);", map, type, name, level_id, point1[0], point1[1], point1[2], point2[0], point2[1], point2[2]); - + SQL_TQuery(g_hSQL, MapZoneChangedCallback, query, StrEqual(map, g_currentMap), DBPrio_Normal); - + return true; } - + return false; } @@ -2724,7 +2682,7 @@ public MapZoneChangedCallback(Handle:owner, Handle:hndl, const String:error[], a Timer_LogError("SQL Error on AddMapZone: %s", error); return; } - + if(data) { if(g_timerMapTier) @@ -2747,10 +2705,10 @@ bool:LoadMapZones() decl String:query[512]; FormatEx(query, sizeof(query), "SELECT * FROM mapzone WHERE map = '%s' ORDER BY level_id ASC;", g_currentMap); SQL_TQuery(g_hSQL, LoadMapZonesCallback, query, _, DBPrio_High); - + return true; } - + return false; } @@ -2758,44 +2716,51 @@ bool:LoadMapZones() public LoadMapZonesCallback(Handle:owner, Handle:hndl, const String:error[], any:data) { g_bZonesLoaded = false; - + if (hndl == INVALID_HANDLE) { Timer_LogError("SQL Error on LoadMapZones: %s", error); return; } - + g_mapZonesCount = 0; DeleteAllZoneEntitys(); - + while (SQL_FetchRow(hndl)) { strcopy(g_mapZones[g_mapZonesCount][Map], 64, g_currentMap); - + g_mapZones[g_mapZonesCount][Id] = SQL_FetchInt(hndl, 0); g_mapZones[g_mapZonesCount][Type] = MapZoneType:SQL_FetchInt(hndl, 1); g_mapZones[g_mapZonesCount][Level_Id] = SQL_FetchInt(hndl, 2); - + g_mapZones[g_mapZonesCount][Point1][0] = SQL_FetchFloat(hndl, 3); g_mapZones[g_mapZonesCount][Point1][1] = SQL_FetchFloat(hndl, 4); g_mapZones[g_mapZonesCount][Point1][2] = SQL_FetchFloat(hndl, 5); - + g_mapZones[g_mapZonesCount][Point2][0] = SQL_FetchFloat(hndl, 6); g_mapZones[g_mapZonesCount][Point2][1] = SQL_FetchFloat(hndl, 7); g_mapZones[g_mapZonesCount][Point2][2] = SQL_FetchFloat(hndl, 8); - + + if(g_mapZones[g_mapZonesCount][Point2][2] < g_mapZones[g_mapZonesCount][Point1][2]) + { + new Float:buffer = g_mapZones[g_mapZonesCount][Point2][2]; + g_mapZones[g_mapZonesCount][Point2][2] = g_mapZones[g_mapZonesCount][Point1][2]; + g_mapZones[g_mapZonesCount][Point1][2] = buffer; + } + decl String:ZoneName[32]; SQL_FetchString(hndl, 10, ZoneName, sizeof(ZoneName)); FormatEx(g_mapZones[g_mapZonesCount][zName], 32, "%s", ZoneName); - + SpawnZoneEntitys(g_mapZonesCount); - + g_mapZonesCount++; } - + g_bZonesLoaded = true; g_bSpawnSpotlights = false; - + /* Forwards */ Call_StartForward(g_OnMapZonesLoaded); Call_Finish(); @@ -2817,7 +2782,7 @@ public OnTimerSqlStop() ConnectSQL() { g_hSQL = Handle:Timer_SqlGetConnection(); - + if (g_hSQL == INVALID_HANDLE) CreateTimer(0.1, Timer_SQLReconnect, _ , TIMER_FLAG_NO_MAPCHANGE); else @@ -2836,38 +2801,38 @@ public OnAdminMenuReady(Handle:topmenu) if (topmenu == hTopMenu) { return; } - + // Save the Handle hTopMenu = topmenu; - + if ((oMapZoneMenu = FindTopMenuCategory(topmenu, "Timer Zones")) == INVALID_TOPMENUOBJECT) { oMapZoneMenu = AddToTopMenu(hTopMenu,"Timer Zones",TopMenuObject_Category,AdminMenu_CategoryHandler,INVALID_TOPMENUOBJECT); } - + AddToTopMenu(hTopMenu, "timer_mapzones_add",TopMenuObject_Item,AdminMenu_AddMapZone, - oMapZoneMenu,"timer_mapzones_add",ADMFLAG_RCON); - + oMapZoneMenu,"timer_mapzones_add",ADMFLAG_BAN); + AddToTopMenu(hTopMenu, "timer_mapzones_remove",TopMenuObject_Item,AdminMenu_RemoveMapZone, - oMapZoneMenu,"timer_mapzones_remove",ADMFLAG_RCON); - + oMapZoneMenu,"timer_mapzones_remove",ADMFLAG_BAN); + AddToTopMenu(hTopMenu, "timer_mapzones_remove_all",TopMenuObject_Item,AdminMenu_RemoveAllMapZones, - oMapZoneMenu,"timer_mapzones_remove_all",ADMFLAG_RCON); - + oMapZoneMenu,"timer_mapzones_remove_all",ADMFLAG_BAN); + AddToTopMenu(hTopMenu, "sm_npc_next",TopMenuObject_Item,AdminMenu_NPC, - oMapZoneMenu,"sm_npc_next",ADMFLAG_RCON); - + oMapZoneMenu,"sm_npc_next",ADMFLAG_BAN); + AddToTopMenu(hTopMenu, "sm_zoneadminmode",TopMenuObject_Item,AdminMenu_AdminMode, - oMapZoneMenu,"sm_zoneadminmode",ADMFLAG_CHANGEMAP); - + oMapZoneMenu,"sm_zoneadminmode",ADMFLAG_BAN); + AddToTopMenu(hTopMenu, "sm_zonereload",TopMenuObject_Item,AdminMenu_Reload, - oMapZoneMenu,"sm_zonereload",ADMFLAG_CHANGEMAP); - + oMapZoneMenu,"sm_zonereload",ADMFLAG_BAN); + AddToTopMenu(hTopMenu, "sm_zone",TopMenuObject_Item,AdminMenu_Teleport, - oMapZoneMenu,"sm_zone",ADMFLAG_CHANGEMAP); + oMapZoneMenu,"sm_zone",ADMFLAG_BAN); } -public AdminMenu_CategoryHandler(Handle:topmenu, +public AdminMenu_CategoryHandler(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, @@ -2881,7 +2846,7 @@ public AdminMenu_CategoryHandler(Handle:topmenu, } } -public AdminMenu_AddMapZone(Handle:topmenu, +public AdminMenu_AddMapZone(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, @@ -2901,7 +2866,7 @@ StartAddingZone(client) DisplaySelectPointMenu(client, 1); } -public AdminMenu_RemoveMapZone(Handle:topmenu, +public AdminMenu_RemoveMapZone(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, @@ -2915,7 +2880,7 @@ public AdminMenu_RemoveMapZone(Handle:topmenu, } } -public AdminMenu_RemoveAllMapZones(Handle:topmenu, +public AdminMenu_RemoveAllMapZones(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, @@ -2924,7 +2889,7 @@ public AdminMenu_RemoveAllMapZones(Handle:topmenu, { if (action == TopMenuAction_DisplayOption) { FormatEx(buffer, maxlength, "Delete All Zones"); - } else if (action == TopMenuAction_SelectOption) + } else if (action == TopMenuAction_SelectOption) { if(param == 0) DeleteAllMapZones(param); @@ -2932,7 +2897,7 @@ public AdminMenu_RemoveAllMapZones(Handle:topmenu, } } -public AdminMenu_NPC(Handle:topmenu, +public AdminMenu_NPC(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, @@ -2941,13 +2906,13 @@ public AdminMenu_NPC(Handle:topmenu, { if (action == TopMenuAction_DisplayOption) { FormatEx(buffer, maxlength, "Create NPC Teleporter"); - } else if (action == TopMenuAction_SelectOption) + } else if (action == TopMenuAction_SelectOption) { CreateNPC(param, 0); } } -public AdminMenu_AdminMode(Handle:topmenu, +public AdminMenu_AdminMode(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, @@ -2956,14 +2921,14 @@ public AdminMenu_AdminMode(Handle:topmenu, { if (action == TopMenuAction_DisplayOption) { FormatEx(buffer, maxlength, "Toggle Admin Mode"); - } else if (action == TopMenuAction_SelectOption) + } else if (action == TopMenuAction_SelectOption) { if(adminmode == 0) { CPrintToChatAll("%s Adminmode enabled!", PLUGIN_PREFIX2); adminmode = 1; } - else + else { CPrintToChatAll("%s Adminmode disabled!", PLUGIN_PREFIX2); adminmode = 0; @@ -2971,7 +2936,7 @@ public AdminMenu_AdminMode(Handle:topmenu, } } -public AdminMenu_Reload(Handle:topmenu, +public AdminMenu_Reload(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, @@ -2980,14 +2945,14 @@ public AdminMenu_Reload(Handle:topmenu, { if (action == TopMenuAction_DisplayOption) { FormatEx(buffer, maxlength, "Zone Reload"); - } else if (action == TopMenuAction_SelectOption) + } else if (action == TopMenuAction_SelectOption) { CPrintToChatAll("%s Zones Reloaded!", PLUGIN_PREFIX2); LoadMapZones(); } } -public AdminMenu_Teleport(Handle:topmenu, +public AdminMenu_Teleport(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, @@ -2996,7 +2961,7 @@ public AdminMenu_Teleport(Handle:topmenu, { if (action == TopMenuAction_DisplayOption) { FormatEx(buffer, maxlength, "Zone Teleport"); - } else if (action == TopMenuAction_SelectOption) + } else if (action == TopMenuAction_SelectOption) { AdminZoneTeleport(param); } @@ -3007,17 +2972,17 @@ DeleteMapZonesMenu(client) if (0 < client < MaxClients) { new Handle:menu = CreateMenu(Handle_DeleteMapZonesMenu); - + SetMenuTitle(menu, "Are you sure!"); - - AddMenuItem(menu, "no", "Oh no"); + AddMenuItem(menu, "no", "Oh no"); AddMenuItem(menu, "no", "Oh no"); - AddMenuItem(menu, "yes", "!!! YES DELETE ALL ZONES !!!"); AddMenuItem(menu, "no", "Oh no"); + AddMenuItem(menu, "yes", "!!! YES DELETE ALL ZONES !!!"); AddMenuItem(menu, "no", "Oh no"); AddMenuItem(menu, "no", "Oh no"); - + AddMenuItem(menu, "no", "Oh no"); + DisplayMenu(menu, client, MENU_TIME_FOREVER); } } @@ -3045,10 +3010,10 @@ ResetMapZoneEditor(client) if(client) { g_mapZoneEditors[client][Step] = 0; - + for (new i = 0; i < 3; i++) g_mapZoneEditors[client][Point1][i] = 0.0; - + for (new i = 0; i < 3; i++) g_mapZoneEditors[client][Point1][i] = 0.0; } @@ -3058,15 +3023,15 @@ DeleteMapZone(client) { new Float:vec[3]; GetClientAbsOrigin(client, vec); - + for (new zone = 0; zone < g_mapZonesCount; zone++) { if (IsInsideBox(vec, g_mapZones[zone][Point1][0], g_mapZones[zone][Point1][1], g_mapZones[zone][Point1][2], g_mapZones[zone][Point2][0], g_mapZones[zone][Point2][1], g_mapZones[zone][Point2][2])) { decl String:query[64]; FormatEx(query, sizeof(query), "DELETE FROM mapzone WHERE id = %d", g_mapZones[zone][Id]); - - SQL_TQuery(g_hSQL, DeleteMapZoneCallback, query, client, DBPrio_Normal); + + SQL_TQuery(g_hSQL, DeleteMapZoneCallback, query, client, DBPrio_Normal); break; } } @@ -3076,7 +3041,7 @@ DeleteAllMapZones(client) { decl String:query[256]; FormatEx(query, sizeof(query), "DELETE FROM mapzone WHERE map = '%s'", g_currentMap); - + SQL_TQuery(g_hSQL, DeleteMapZoneCallback, query, client, DBPrio_Normal); } @@ -3087,9 +3052,9 @@ public DeleteMapZoneCallback(Handle:owner, Handle:hndl, const String:error[], an Timer_LogError("SQL Error on DeleteMapZone: %s", error); return; } - + LoadMapZones(); - + if (IsClientInGame(data)) CPrintToChat(data, PLUGIN_PREFIX, "Map Zone Delete"); } @@ -3097,19 +3062,19 @@ public DeleteMapZoneCallback(Handle:owner, Handle:hndl, const String:error[], an DisplaySelectPointMenu(client, n) { new Handle:panel = CreatePanel(); - + decl String:message[255]; decl String:first[32], String:second[32]; FormatEx(first, sizeof(first), "%t", "FIRST"); FormatEx(second, sizeof(second), "%t", "SECOND"); - + FormatEx(message, sizeof(message), "%t", "Point Select Panel", (n == 1) ? first : second); - + DrawPanelItem(panel, message, ITEMDRAW_RAWLINE); - + FormatEx(message, sizeof(message), "%t", "Cancel"); DrawPanelItem(panel, message); - + SendPanelToClient(panel, client, PointSelect, 540); CloseHandle(panel); } @@ -3117,28 +3082,28 @@ DisplaySelectPointMenu(client, n) DisplayPleaseWaitMenu(client) { new Handle:panel = CreatePanel(); - + decl String:wait[64]; FormatEx(wait, sizeof(wait), "%t", "Please wait"); DrawPanelItem(panel, wait, ITEMDRAW_RAWLINE); - + SendPanelToClient(panel, client, PointSelect, 540); CloseHandle(panel); } public PointSelect(Handle:menu, MenuAction:action, param1, param2) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); - } - else if (action == MenuAction_Select) + } + else if (action == MenuAction_Select) { - if (param2 == MenuCancel_Exit && hTopMenu != INVALID_HANDLE) + if (param2 == MenuCancel_Exit && hTopMenu != INVALID_HANDLE) { DisplayTopMenu(hTopMenu, param1, TopMenuPosition_LastCategory); } - + ResetMapZoneEditor(param1); } } @@ -3146,10 +3111,10 @@ public PointSelect(Handle:menu, MenuAction:action, param1, param2) public Action:ChangeStep(Handle:timer, any:serial) { new client = GetClientFromSerial(serial); - + g_mapZoneEditors[client][Step] = 2; CreateTimer(0.1, DrawAdminBox, GetClientSerial(client), TIMER_REPEAT); - + DisplaySelectPointMenu(client, 2); } @@ -3164,7 +3129,7 @@ stock CheckIllegalTeleport(client) { return true; } - + return false; } @@ -3174,26 +3139,26 @@ stock CreateNPC(client, step, bool:double = false) { if(!IsClientInGame(client)) return; - + if(step == 0) { new Float:vec[3]; GetClientAbsOrigin(client, vec); g_mapZoneEditors[client][Point1] = vec; new Handle:menu = CreateMenu(Handle_Menu_NPC); - + SetMenuTitle(menu, "Timer Menu"); - + AddMenuItem(menu, "npc_reset", "Reset NPC Point"); AddMenuItem(menu, "dest", "Set Destination (Teammate)"); AddMenuItem(menu, "dest_double", "Set Destination (Both Players)"); - + DisplayMenu(menu, client, MENU_TIME_FOREVER); } else { new String:lvlbuffer[32]; - + new hcount = LEVEL_START; for (new zone = 0; zone < g_mapZonesCount; zone++) { @@ -3201,21 +3166,21 @@ stock CreateNPC(client, step, bool:double = false) if(g_mapZones[zone][Level_Id] <= hcount) continue; hcount = g_mapZones[zone][Level_Id]; } - + hcount++; - + FormatEx(lvlbuffer, sizeof(lvlbuffer), "Level %d", hcount); - + new Float:vec[3]; GetClientAbsOrigin(client, vec); g_mapZoneEditors[client][Point2] = vec; - + new Float:point1[3]; Array_Copy(g_mapZoneEditors[client][Point1], point1, 3); - + new Float:point2[3]; Array_Copy(g_mapZoneEditors[client][Point2], point2, 3); - + if(!double) { if(!AddMapZone(g_currentMap, MapZoneType:ZtNPC_Next, lvlbuffer, hcount, point1, point2)) @@ -3257,23 +3222,23 @@ public Handle_Menu_NPC(Handle:menu, MenuAction:action, client, itemNum) public Action:DrawAdminBox(Handle:timer, any:serial) { new client = GetClientFromSerial(serial); - + if (g_mapZoneEditors[client][Step] == 0) { return Plugin_Stop; } - + new Float:a[3], Float:b[3]; - + Array_Copy(g_mapZoneEditors[client][Point1], b, 3); - + if (g_mapZoneEditors[client][Step] == 3) Array_Copy(g_mapZoneEditors[client][Point2], a, 3); else GetClientAbsOrigin(client, a); - + new color[4] = {255, 255, 255, 255}; - + DrawBox(a, b, 0.1, color, false); return Plugin_Continue; } @@ -3284,15 +3249,15 @@ public Action:DrawZones(Handle:timer) { new Float:point1[3]; Array_Copy(g_mapZones[zone][Point1], point1, 3); - + new Float:point2[3]; Array_Copy(g_mapZones[zone][Point2], point2, 3); - + if (point1[2] < point2[2]) point2[2] = point1[2]; else point1[2] = point2[2]; - + if (g_mapZones[zone][Type] == ZtStart) DrawBox(point1, point2, 1.0, g_startColor, true, precache_laser_start); else if (g_mapZones[zone][Type] == ZtEnd) @@ -3302,7 +3267,7 @@ public Action:DrawZones(Handle:timer) else if (g_mapZones[zone][Type] == ZtBonusEnd || g_mapZones[zone][Type] == ZtBonus2End || g_mapZones[zone][Type] == ZtBonus3End || g_mapZones[zone][Type] == ZtBonus4End || g_mapZones[zone][Type] == ZtBonus5End) DrawBox(point1, point2, 1.0, g_bonusendColor, true, precache_laser_bonus_end); } - + return Plugin_Continue; } @@ -3312,10 +3277,10 @@ DrawZone(zone, bool:flat) { new Float:point1[3]; Array_Copy(g_mapZones[zone][Point1], point1, 3); - + new Float:point2[3]; Array_Copy(g_mapZones[zone][Point2], point2, 3); - + if(flat) { if (point1[2] < point2[2]) @@ -3323,7 +3288,7 @@ DrawZone(zone, bool:flat) else point1[2] = point2[2]; } - + if(flat) { if (g_mapZones[zone][Type] == ZtStop) @@ -3347,7 +3312,7 @@ DrawZone(zone, bool:flat) { DrawBox(point1, point2, 1.0, g_startColor, flat); } - + g_MapZoneDrawDelayTimer[zone] = CreateTimer(2.0, Timer_DelayDraw, zone, TIMER_FLAG_NO_MAPCHANGE); } } @@ -3355,7 +3320,7 @@ DrawZone(zone, bool:flat) public Action:Timer_DelayDraw(Handle:timer, any:zone) { g_MapZoneDrawDelayTimer[zone] = INVALID_HANDLE; - + return Plugin_Stop; } @@ -3363,13 +3328,13 @@ public TraceToEntity(client) { new Float:vecClientEyePos[3], Float:vecClientEyeAng[3]; GetClientEyePosition(client, vecClientEyePos); - GetClientEyeAngles(client, vecClientEyeAng); - + GetClientEyeAngles(client, vecClientEyeAng); + TR_TraceRayFilter(vecClientEyePos, vecClientEyeAng, MASK_PLAYERSOLID, RayType_Infinite, TraceASDF, client); - + if (TR_DidHit(INVALID_HANDLE)) return (TR_GetEntityIndex(INVALID_HANDLE)); - + return (-1); } @@ -3384,6 +3349,14 @@ bool:IsPlayerTouchingSpeedZone(client) return true; if(g_bPreSpeedBonusStart && Timer_IsPlayerTouchingZoneType(client, ZtBonusStart)) return true; + if(g_bPreSpeedBonusStart && Timer_IsPlayerTouchingZoneType(client, ZtBonus2Start)) + return true; + if(g_bPreSpeedBonusStart && Timer_IsPlayerTouchingZoneType(client, ZtBonus3Start)) + return true; + if(g_bPreSpeedBonusStart && Timer_IsPlayerTouchingZoneType(client, ZtBonus4Start)) + return true; + if(g_bPreSpeedBonusStart && Timer_IsPlayerTouchingZoneType(client, ZtBonus5Start)) + return true; if(Timer_IsPlayerTouchingZoneType(client, ZtLimitSpeed)) return true; if(Timer_IsPlayerTouchingZoneType(client, ZtFullBooster)) @@ -3404,7 +3377,7 @@ bool:IsPlayerTouchingSpeedZone(client) return true; if(Timer_IsPlayerTouchingZoneType(client, ZtHover)) return true; - + return false; } @@ -3422,18 +3395,18 @@ ChangePlayerVelocity(client) return; if(g_mapZonesCount < 1) return; - + new Float:vec[3]; GetClientAbsOrigin(client, vec); - + new style = Timer_GetStyle(client); new Float:maxspeed = g_Physics[style][StyleBlockPreSpeeding]; - + if(!IsPlayerTouchingSpeedZone(client)) return; - + new Float:push_maxspeed = GetEntPropFloat(client, Prop_Send, "m_flMaxspeed"); - + if (Timer_IsPlayerTouchingZoneType(client, ZtFullBooster)) { CheckVelocity(client, 4, maxspeed); @@ -3500,29 +3473,29 @@ IsInsideBox(Float:fPCords[3], Float:fbsx, Float:fbsy, Float:fbsz, Float:fbex, Fl new Float:fpx = fPCords[0]; new Float:fpy = fPCords[1]; new Float:fpz = fPCords[2]+30; - + new bool:bX = false; new bool:bY = false; new bool:bZ = false; - + if (fbsx > fbex && fpx <= fbsx && fpx >= fbex) bX = true; else if (fbsx < fbex && fpx >= fbsx && fpx <= fbex) bX = true; - + if (fbsy > fbey && fpy <= fbsy && fpy >= fbey) bY = true; else if (fbsy < fbey && fpy >= fbsy && fpy <= fbey) bY = true; - + if (fbsz > fbez && fpz <= fbsz && fpz >= fbez) bZ = true; else if (fbsz < fbez && fpz >= fbsz && fpz <= fbez) bZ = true; - + if (bX && bY && bZ) return true; - + return false; } @@ -3530,7 +3503,7 @@ DrawBox(Float:fFrom[3], Float:fTo[3], Float:fLife, color[4], bool:flat, iSpriteI { if(iSpriteIndex == 0) iSpriteIndex = precache_laser_default; - + if(g_Settings[ZoneSprites] || !flat) { //initialize tempoary variables bottom front @@ -3541,7 +3514,7 @@ DrawBox(Float:fFrom[3], Float:fTo[3], Float:fLife, color[4], bool:flat, iSpriteI fLeftBottomFront[2] = fTo[2]-g_Settings[ZoneBeamHeight]; else fLeftBottomFront[2] = fTo[2]; - + decl Float:fRightBottomFront[3]; fRightBottomFront[0] = fTo[0]; fRightBottomFront[1] = fFrom[1]; @@ -3549,7 +3522,7 @@ DrawBox(Float:fFrom[3], Float:fTo[3], Float:fLife, color[4], bool:flat, iSpriteI fRightBottomFront[2] = fTo[2]-g_Settings[ZoneBeamHeight]; else fRightBottomFront[2] = fTo[2]; - + //initialize tempoary variables bottom back decl Float:fLeftBottomBack[3]; fLeftBottomBack[0] = fFrom[0]; @@ -3558,7 +3531,7 @@ DrawBox(Float:fFrom[3], Float:fTo[3], Float:fLife, color[4], bool:flat, iSpriteI fLeftBottomBack[2] = fTo[2]-g_Settings[ZoneBeamHeight]; else fLeftBottomBack[2] = fTo[2]; - + decl Float:fRightBottomBack[3]; fRightBottomBack[0] = fTo[0]; fRightBottomBack[1] = fTo[1]; @@ -3566,7 +3539,7 @@ DrawBox(Float:fFrom[3], Float:fTo[3], Float:fLife, color[4], bool:flat, iSpriteI fRightBottomBack[2] = fTo[2]-g_Settings[ZoneBeamHeight]; else fRightBottomBack[2] = fTo[2]; - + //initialize tempoary variables top front decl Float:fLeftTopFront[3]; fLeftTopFront[0] = fFrom[0]; @@ -3582,7 +3555,7 @@ DrawBox(Float:fFrom[3], Float:fTo[3], Float:fLife, color[4], bool:flat, iSpriteI fRightTopFront[2] = fFrom[2]+g_Settings[ZoneBeamHeight]; else fRightTopFront[2] = fFrom[2]; - + //initialize tempoary variables top back decl Float:fLeftTopBack[3]; fLeftTopBack[0] = fFrom[0]; @@ -3598,29 +3571,29 @@ DrawBox(Float:fFrom[3], Float:fTo[3], Float:fLife, color[4], bool:flat, iSpriteI fRightTopBack[2] = fFrom[2]+g_Settings[ZoneBeamHeight]; else fRightTopBack[2] = fFrom[2]; - + new Float:width = g_Settings[ZoneBeamThickness]; - + if(flat == false) width = 0.5; - + //create the box TE_SetupBeamPoints(fLeftTopFront,fRightTopFront,iSpriteIndex,0,0,0,0.99,width,width,10,0.0,color,10);TE_SendToAll(0.0); TE_SetupBeamPoints(fLeftTopBack,fLeftTopFront,iSpriteIndex,0,0,0,0.99,width,width,10,0.0,color,10);TE_SendToAll(0.0); TE_SetupBeamPoints(fRightTopBack,fLeftTopBack,iSpriteIndex,0,0,0,0.99,width,width,10,0.0,color,10);TE_SendToAll(0.0); TE_SetupBeamPoints(fRightTopFront,fRightTopBack,iSpriteIndex,0,0,0,0.99,width,width,10,0.0,color,10);TE_SendToAll(0.0); - + if(!flat) { TE_SetupBeamPoints(fRightBottomFront,fLeftBottomFront,iSpriteIndex,0,0,0,fLife,width,width,0,0.0,color,0);TE_SendToAll(0.0); TE_SetupBeamPoints(fLeftBottomBack,fLeftBottomFront,iSpriteIndex,0,0,0,fLife,width,width,0,0.0,color,0);TE_SendToAll(0.0); TE_SetupBeamPoints(fLeftTopFront,fLeftBottomFront,iSpriteIndex,0,0,0,fLife,width,width,0,0.0,color,0);TE_SendToAll(0.0); - - + + TE_SetupBeamPoints(fLeftBottomBack,fRightBottomBack,iSpriteIndex,0,0,0,fLife,width,width,0,0.0,color,0);TE_SendToAll(0.0); TE_SetupBeamPoints(fRightBottomFront,fRightBottomBack,iSpriteIndex,0,0,0,fLife,width,width,0,0.0,color,0);TE_SendToAll(0.0); TE_SetupBeamPoints(fRightTopBack,fRightBottomBack,iSpriteIndex,0,0,0,fLife,width,width,0,0.0,color,0);TE_SendToAll(0.0); - + TE_SetupBeamPoints(fRightTopFront,fRightBottomFront,iSpriteIndex,0,0,0,fLife,width,width,0,0.0,color,0);TE_SendToAll(0.0); TE_SetupBeamPoints(fLeftTopBack,fLeftBottomBack,iSpriteIndex,0,0,0,fLife,width,width,0,0.0,color,0);TE_SendToAll(0.0); } @@ -3851,28 +3824,28 @@ stock ZoneEffectTesla(targetzone) TeleportEntity(laserent, center, zero, zero); - AcceptEntityInput(laserent, "TurnOn"); + AcceptEntityInput(laserent, "TurnOn"); AcceptEntityInput(laserent, "DoSpark"); } GetZoneEntityCount() { new count; - + for (new i = MaxClients; i <= 2047; i++) { if(!IsValidEntity(i)) continue; - + new String:EntName[256]; Entity_GetName(i, EntName, sizeof(EntName)); - + new valid = StrContains(EntName, "#TIMER_"); if(valid > -1) { count++; } } - + return count; } @@ -3882,25 +3855,25 @@ DeleteAllZoneEntitys() { g_MapZoneDrawDelayTimer[i] = INVALID_HANDLE; g_MapZoneEntityZID[i] = -1; - + if(!IsValidEntity(i)) continue; - + new String:EntName[256]; Entity_GetName(i, EntName, sizeof(EntName)); - + if(StrContains(EntName, "#TIMER_NPC") != -1) SDKUnhook(i, SDKHook_StartTouch, NPC_Use); - + if(StrContains(EntName, "#TIMER_TRIGGER") != -1) { SDKUnhook(i, SDKHook_StartTouch, StartTouchTrigger); SDKUnhook(i, SDKHook_EndTouch, EndTouchTrigger); SDKUnhook(i, SDKHook_Touch, OnTouchTrigger); } - + if(StrContains(EntName, "#TIMER_") != -1) DeleteEntity(i); - + for (new client = 1; client <= MaxClients; client++) g_bZone[i][client] = false; } @@ -3918,13 +3891,13 @@ SpawnZoneEntitys(zone) // No valid zone return; } - + //Spawn debug entitys ine each corner if(adminmode == 1) { SpawnZoneDebugEntitys(zone); } - + //Spawn NPCs if(g_mapZones[zone][Type] == ZtNPC_Next || g_mapZones[zone][Type] == ZtNPC_Next_Double) { @@ -3940,27 +3913,27 @@ SpawnZoneEntitys(zone) { SpawnZoneTrigger(zone); } - + //Spawn spot lights if(g_bSpawnSpotlights && g_Settings[ZoneSpotlights]) { - if(g_mapZones[zone][Type] == ZtStart || - g_mapZones[zone][Type] == ZtEnd || - g_mapZones[zone][Type] == ZtLevel || - g_mapZones[zone][Type] == ZtBonusStart || - g_mapZones[zone][Type] == ZtBonus2Start || - g_mapZones[zone][Type] == ZtBonus3Start || - g_mapZones[zone][Type] == ZtBonus4Start || - g_mapZones[zone][Type] == ZtBonus5Start || - g_mapZones[zone][Type] == ZtBonusEnd || - g_mapZones[zone][Type] == ZtBonus2End || - g_mapZones[zone][Type] == ZtBonus3End || - g_mapZones[zone][Type] == ZtBonus4End || - g_mapZones[zone][Type] == ZtBonus5End || - g_mapZones[zone][Type] == ZtBonusLevel || - g_mapZones[zone][Type] == ZtBonus2Level || - g_mapZones[zone][Type] == ZtBonus3Level || - g_mapZones[zone][Type] == ZtBonus4Level || + if(g_mapZones[zone][Type] == ZtStart || + g_mapZones[zone][Type] == ZtEnd || + g_mapZones[zone][Type] == ZtLevel || + g_mapZones[zone][Type] == ZtBonusStart || + g_mapZones[zone][Type] == ZtBonus2Start || + g_mapZones[zone][Type] == ZtBonus3Start || + g_mapZones[zone][Type] == ZtBonus4Start || + g_mapZones[zone][Type] == ZtBonus5Start || + g_mapZones[zone][Type] == ZtBonusEnd || + g_mapZones[zone][Type] == ZtBonus2End || + g_mapZones[zone][Type] == ZtBonus3End || + g_mapZones[zone][Type] == ZtBonus4End || + g_mapZones[zone][Type] == ZtBonus5End || + g_mapZones[zone][Type] == ZtBonusLevel || + g_mapZones[zone][Type] == ZtBonus2Level || + g_mapZones[zone][Type] == ZtBonus3Level || + g_mapZones[zone][Type] == ZtBonus4Level || g_mapZones[zone][Type] == ZtBonus5Level) { SpawnZoneSpotLights(zone); @@ -3975,19 +3948,19 @@ SpawnZoneTrigger(zone) center[0] = (g_mapZones[zone][Point1][0] + g_mapZones[zone][Point2][0]) / 2.0; center[1] = (g_mapZones[zone][Point1][1] + g_mapZones[zone][Point2][1]) / 2.0; center[2] = g_mapZones[zone][Point1][2]; - + // Min & max bounds - new Float:minbounds[3]; - new Float:maxbounds[3]; - + new Float:minbounds[3]; + new Float:maxbounds[3]; + minbounds[0] = FloatAbs(g_mapZones[zone][Point1][0]-g_mapZones[zone][Point2][0]) / -2.0; minbounds[1] = FloatAbs(g_mapZones[zone][Point1][1]-g_mapZones[zone][Point2][1]) / -2.0; minbounds[2] = -1.0; // Just to be save it's not buggy like a defective contact - + maxbounds[0] = FloatAbs(g_mapZones[zone][Point1][0]-g_mapZones[zone][Point2][0]) / 2.0; maxbounds[1] = FloatAbs(g_mapZones[zone][Point1][1]-g_mapZones[zone][Point2][1]) / 2.0; maxbounds[2] = FloatAbs(g_mapZones[zone][Point1][2]-g_mapZones[zone][Point2][2]); - + // Resize trigger (by default it's set to 16.0). A player is 32.0 unity wide, so we need to resize the trigger to have a touching border between the legs minbounds[0] += g_Settings[ZoneResize]; minbounds[1] += g_Settings[ZoneResize]; @@ -3995,17 +3968,17 @@ SpawnZoneTrigger(zone) maxbounds[0] -= g_Settings[ZoneResize]; maxbounds[1] -= g_Settings[ZoneResize]; maxbounds[2] -= g_Settings[ZoneResize]; - + // Spawn trigger new entity = CreateEntityByName("trigger_multiple"); if (entity > 0) { // Attach zoneID to the entity g_MapZoneEntityZID[entity] = zone; - + // Give our trigger_multiple a model (It's totally unimportant which one you are using) - SetEntityModel(entity, "models/props_junk/wood_crate001a.mdl"); - + SetEntityModel(entity, "models/props_junk/wood_crate001a.mdl"); + if(IsValidEntity(entity)) { // Spawnflags for "trigger_multiple" @@ -4016,29 +3989,29 @@ SpawnZoneTrigger(zone) // 16 - only non-player NPCs can trigger this by touch // 128 - Start off, has to be activated by a target_activate to be touchable/usable // 256 - multiple players can trigger the entity at the same time - - DispatchKeyValue(entity, "spawnflags", "257"); - + + DispatchKeyValue(entity, "spawnflags", "257"); + DispatchKeyValue(entity, "StartDisabled", "0"); - + // Give our entity a unique name tag, so we can delete it also if the plugins was reloaded without deleting them new String:EntName[256]; FormatEx(EntName, sizeof(EntName), "#TIMER_Trigger_%d", g_mapZones[zone][Id]); DispatchKeyValue(entity, "targetname", EntName); - + if(DispatchSpawn(entity)) { ActivateEntity(entity); - + // Set the size of our trigger_multiple box SetEntPropVector(entity, Prop_Send, "m_vecMins", minbounds); SetEntPropVector(entity, Prop_Send, "m_vecMaxs", maxbounds); - + SetEntProp(entity, Prop_Send, "m_nSolidType", 2); SetEntProp(entity, Prop_Send, "m_fEffects", GetEntProp(entity, Prop_Send, "m_fEffects") | 32); - + TeleportEntity(entity, center, NULL_VECTOR, NULL_VECTOR); - + SDKHook(entity, SDKHook_StartTouch, StartTouchTrigger); SDKHook(entity, SDKHook_EndTouch, EndTouchTrigger); SDKHook(entity, SDKHook_Touch, OnTouchTrigger); @@ -4053,36 +4026,36 @@ SpawnZoneSpotLights(zone) fFrom[0] = g_mapZones[zone][Point2][0]; fFrom[1] = g_mapZones[zone][Point2][1]; fFrom[2] = g_mapZones[zone][Point2][2]; - + new Float:fTo[3]; fTo[0] = g_mapZones[zone][Point1][0]; fTo[1] = g_mapZones[zone][Point1][1]; fTo[2] = g_mapZones[zone][Point1][2]; - + //initialize tempoary variables bottom front decl Float:fLeftBottomFront[3]; fLeftBottomFront[0] = fFrom[0]; fLeftBottomFront[1] = fFrom[1]; fLeftBottomFront[2] = fTo[2]+20; - + decl Float:fRightBottomFront[3]; fRightBottomFront[0] = fTo[0]; fRightBottomFront[1] = fFrom[1]; fRightBottomFront[2] = fTo[2]+20; - + //initialize tempoary variables bottom back decl Float:fLeftBottomBack[3]; fLeftBottomBack[0] = fFrom[0]; fLeftBottomBack[1] = fTo[1]; fLeftBottomBack[2] = fTo[2]+20; - + decl Float:fRightBottomBack[3]; fRightBottomBack[0] = fTo[0]; fRightBottomBack[1] = fTo[1]; fRightBottomBack[2] = fTo[2]+20; - + new Float:ang[3], Float:color[3]; - + if(g_mapZones[zone][Type] == ZtStart) { color[0] = float(g_startColor[0]); @@ -4119,9 +4092,9 @@ SpawnZoneSpotLights(zone) color[1] = float(g_bonusendColor[1]); color[2] = float(g_bonusendColor[2]); } - + ang[0] = -90.0; - + SpawnSpotLight(fLeftBottomFront, color, ang); SpawnSpotLight(fRightBottomFront, color, ang); SpawnSpotLight(fLeftBottomBack, color, ang); @@ -4131,47 +4104,47 @@ SpawnZoneSpotLights(zone) stock SpawnSpotLight(Float:pos[3], Float:color[3], Float:ang[3]) { pos[2] -= 16.0; - + new entity = CreateEntityByName("point_spotlight"); - + decl String:sAng[32]; Format(sAng, sizeof(sAng), "%d %d %d", RoundToFloor(ang[0]), RoundToFloor(ang[1]), RoundToFloor(ang[2])); - - + + decl String:EntName[256]; FormatEx(EntName, sizeof(EntName), "#TIMER_SPOTLIGHT_%d_%d_%d", RoundToFloor(pos[0]), RoundToFloor(pos[1]), RoundToFloor(pos[2])); DispatchKeyValue(entity, "targetname", EntName); - + DispatchKeyValue(entity, "SpotlightLength", "350"); DispatchKeyValue(entity, "SpotlightWidth", "25"); DispatchKeyValue(entity, "rendermode", "0"); DispatchKeyValue(entity, "scale", "1"); DispatchKeyValue(entity, "renderamt", "64"); DispatchKeyValueVector(entity, "rendercolor", color); - + DispatchKeyValue(entity, "HDRColorScale", "0.1"); DispatchKeyValue(entity, "HaloScale", "1"); DispatchKeyValue(entity, "fadescale", "1"); - + DispatchKeyValue(entity, "brightness", "1"); - + DispatchKeyValue(entity, "_light", "255 255 255 255"); DispatchKeyValue(entity, "style", "0"); - + DispatchKeyValue(entity, "pitch", "0 0 0"); DispatchKeyValue(entity, "renderamt", "255"); - + DispatchKeyValue(entity, "disablereceiveshadows", "1"); - + //-75 x 0 DispatchKeyValue(entity, "angles", sAng); - + DispatchKeyValue(entity, "spawnflags", "3"); - + DispatchSpawn(entity); - + TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR); - + AcceptEntityInput(entity, "LightOn"); } @@ -4181,12 +4154,12 @@ SpawnNPC(zone) vecNPC[0] = g_mapZones[zone][Point1][0]; vecNPC[1] = g_mapZones[zone][Point1][1]; vecNPC[2] = g_mapZones[zone][Point1][2]; - + new Float:vecDestination[3]; vecDestination[0] = g_mapZones[zone][Point2][0]; vecDestination[1] = g_mapZones[zone][Point2][1]; vecDestination[2] = g_mapZones[zone][Point2][2]; - + new String:ModePath[256]; if(g_mapZones[zone][Type] == ZtNPC_Next) { @@ -4198,24 +4171,24 @@ SpawnNPC(zone) PrecacheModel(g_Settings[NPC_Double_Path], true); FormatEx(ModePath, sizeof(ModePath), "%s", g_Settings[NPC_Double_Path]); } - + decl String:EntName[256]; FormatEx(EntName, sizeof(EntName), "#TIMER_NPC_%d", g_mapZones[zone][Id]); - + new String:Classname[] = "prop_physics_override"; - + new entity1 = CreateEntityByName(Classname); SetEntityModel(entity1, ModePath); - + DispatchKeyValue(entity1, "targetname", EntName); - + DispatchSpawn(entity1); AcceptEntityInput(entity1, "DisableMotion"); AcceptEntityInput(entity1, "DisableShadow"); TeleportEntity(entity1, vecNPC, NULL_VECTOR, NULL_VECTOR); - + g_mapZones[zone][NPC] = entity1; - + SDKHook(entity1, SDKHook_StartTouch, NPC_Use); } @@ -4225,59 +4198,59 @@ SpawnZoneDebugEntitys(zone) { if(g_mapZones[zone][Type] == ZtNPC_Next || g_mapZones[zone][Type] == ZtNPC_Next_Double) return; - + new Float:fFrom[3]; fFrom[0] = g_mapZones[zone][Point2][0]; fFrom[1] = g_mapZones[zone][Point2][1]; fFrom[2] = g_mapZones[zone][Point2][2]; - + new Float:fTo[3]; fTo[0] = g_mapZones[zone][Point1][0]; fTo[1] = g_mapZones[zone][Point1][1]; fTo[2] = g_mapZones[zone][Point1][2]; - + //initialize tempoary variables bottom front decl Float:fLeftBottomFront[3]; fLeftBottomFront[0] = fFrom[0]; fLeftBottomFront[1] = fFrom[1]; fLeftBottomFront[2] = fTo[2]+20; - + decl Float:fRightBottomFront[3]; fRightBottomFront[0] = fTo[0]; fRightBottomFront[1] = fFrom[1]; fRightBottomFront[2] = fTo[2]+20; - + //initialize tempoary variables bottom back decl Float:fLeftBottomBack[3]; fLeftBottomBack[0] = fFrom[0]; fLeftBottomBack[1] = fTo[1]; fLeftBottomBack[2] = fTo[2]+20; - + decl Float:fRightBottomBack[3]; fRightBottomBack[0] = fTo[0]; fRightBottomBack[1] = fTo[1]; fRightBottomBack[2] = fTo[2]+20; - + PrecacheModel("models/props_junk/trafficcone001a.mdl", true); - + decl String:EntName[256]; FormatEx(EntName, sizeof(EntName), "#TIMER_Zone_%d", g_mapZones[zone][Id]); - + new String:ModePath[] = "models/props_junk/trafficcone001a.mdl"; new String:Classname[] = "prop_physics_override"; - + new entity1 = CreateEntityByName(Classname); SetEntityModel(entity1, ModePath); SetEntProp(entity1, Prop_Data, "m_CollisionGroup", 1); SetEntProp(entity1, Prop_Send, "m_usSolidFlags", 12); SetEntProp(entity1, Prop_Send, "m_nSolidType", 6); - SetEntityMoveType(entity1, MOVETYPE_NONE); + SetEntityMoveType(entity1, MOVETYPE_NONE); DispatchKeyValue(entity1, "targetname", EntName); DispatchSpawn(entity1); AcceptEntityInput(entity1, "DisableMotion"); AcceptEntityInput(entity1, "DisableShadow"); TeleportEntity(entity1, fRightBottomBack, NULL_VECTOR, NULL_VECTOR); - + new entity2 = CreateEntityByName(Classname); SetEntityModel(entity2, ModePath); SetEntProp(entity2, Prop_Data, "m_CollisionGroup", 1); @@ -4289,7 +4262,7 @@ SpawnZoneDebugEntitys(zone) AcceptEntityInput(entity2, "DisableMotion"); AcceptEntityInput(entity2, "DisableShadow"); TeleportEntity(entity2, fRightBottomFront, NULL_VECTOR, NULL_VECTOR); - + new entity3 = CreateEntityByName(Classname); SetEntityModel(entity3, ModePath); SetEntProp(entity3, Prop_Data, "m_CollisionGroup", 1); @@ -4301,7 +4274,7 @@ SpawnZoneDebugEntitys(zone) AcceptEntityInput(entity3, "DisableMotion"); AcceptEntityInput(entity3, "DisableShadow"); TeleportEntity(entity3, fLeftBottomFront, NULL_VECTOR, NULL_VECTOR); - + new entity4 = CreateEntityByName(Classname); SetEntityModel(entity4, ModePath); SetEntProp(entity4, Prop_Data, "m_CollisionGroup", 1); @@ -4314,7 +4287,7 @@ SpawnZoneDebugEntitys(zone) AcceptEntityInput(entity4, "DisableMotion"); AcceptEntityInput(entity4, "DisableShadow"); TeleportEntity(entity4, fLeftBottomBack, NULL_VECTOR, NULL_VECTOR); - + if(g_mapZones[zone][Type] == ZtLevel || g_mapZones[zone][Type] == ZtStart || g_mapZones[zone][Type] == ZtEnd) { SetEntityRenderColor(entity1, 0, 255, 0, 200); @@ -4369,29 +4342,29 @@ Menu_NPC_Next(client, zone) { if (0 < client < MaxClients) { - + if(adminmode == 1 && Client_IsAdmin(client)) { new Handle:menu = CreateMenu(Handle_Menu_NPC_Delete); - + SetMenuTitle(menu, "Delete this NPC?"); - + AddMenuItem(menu, "yes", "Yes"); AddMenuItem(menu, "no", "No!"); - + DisplayMenu(menu, client, MENU_TIME_FOREVER); - + g_iTargetNPC[client] = zone; } else if(g_Settings[NPCConfirm]) { new Handle:menu = CreateMenu(Handle_Menu_NPC_Next); - + SetMenuTitle(menu, "Do you like to teleport?"); - + AddMenuItem(menu, "yes", "Yes Please"); AddMenuItem(menu, "no", "Not now!"); - + DisplayMenu(menu, client, MENU_TIME_FOREVER); } else @@ -4403,12 +4376,12 @@ Menu_NPC_Next(client, zone) vecDestination[0] = g_mapZones[g_iClientLastTrackZone[client]][Point2][0]; vecDestination[1] = g_mapZones[g_iClientLastTrackZone[client]][Point2][1]; vecDestination[2] = g_mapZones[g_iClientLastTrackZone[client]][Point2][2]; - - if(Timer_IsPlayerTouchingZoneType(client, ZtStart)) Timer_SetIgnoreEndTouchStart(client, 1); - + + if(Timer_IsPlayerTouchingStartZone(client)) Timer_SetIgnoreEndTouchStart(client, 1); + new mate; if(g_timerTeams) mate = Timer_GetClientTeammate(client); - + if(mate > 0) { if(g_mapZones[zone][Type] == ZtNPC_Next_Double) @@ -4416,7 +4389,7 @@ Menu_NPC_Next(client, zone) TeleportEntity(client, vecDestination, NULL_VECTOR, velStop); CreateTimer(1.5, SetBlockable, client, TIMER_FLAG_NO_MAPCHANGE); SetPush(client); - + TeleportEntity(mate, vecDestination, NULL_VECTOR, velStop); CreateTimer(1.5, SetBlockable, mate, TIMER_FLAG_NO_MAPCHANGE); SetPush(mate); @@ -4450,12 +4423,12 @@ public Handle_Menu_NPC_Next(Handle:menu, MenuAction:action, client, itemNum) vecDestination[0] = g_mapZones[g_iClientLastTrackZone[client]][Point2][0]; vecDestination[1] = g_mapZones[g_iClientLastTrackZone[client]][Point2][1]; vecDestination[2] = g_mapZones[g_iClientLastTrackZone[client]][Point2][2]; - - if(Timer_IsPlayerTouchingZoneType(client, ZtStart)) Timer_SetIgnoreEndTouchStart(client, 1); - + + if(Timer_IsPlayerTouchingStartZone(client)) Timer_SetIgnoreEndTouchStart(client, 1); + new mate; if(g_timerTeams) mate= Timer_GetClientTeammate(client); - + if(mate > 0) { if(Timer_GetCoopStatus(client)) @@ -4469,7 +4442,7 @@ public Handle_Menu_NPC_Next(Handle:menu, MenuAction:action, client, itemNum) } else if(StrEqual(info, "no")) { - + } } } @@ -4486,15 +4459,15 @@ public Handle_Menu_NPC_Delete(Handle:menu, MenuAction:action, client, itemNum) if(StrEqual(info, "yes")) { new zone = g_iTargetNPC[client]; - + decl String:query[64]; FormatEx(query, sizeof(query), "DELETE FROM mapzone WHERE id = %d", g_mapZones[zone][Id]); - + SQL_TQuery(g_hSQL, DeleteMapZoneCallback, query, client, DBPrio_Normal); } else if(StrEqual(info, "no")) { - + } } } @@ -4504,7 +4477,7 @@ ParseColor(const String:color[], result[]) { decl String:buffers[4][4]; ExplodeString(color, " ", buffers, sizeof(buffers), sizeof(buffers[])); - + for (new i = 0; i < sizeof(buffers); i++) result[i] = StringToInt(buffers[i]); } @@ -4517,14 +4490,14 @@ stock bool:Tele_Level(client, level) { if(g_mapZones[mapZone][Level_Id] < LEVEL_START) continue; - + if (g_mapZones[mapZone][Level_Id] == level) { return Tele_Zone(client, mapZone); } } } - + return false; } @@ -4532,60 +4505,42 @@ stock bool:Tele_Zone(client, zone, bool:stopspeed = true, bool:overwrite_physics { if(!IsClientInGame(client)) return false; - + // Don't teleport from inside a startzone to the same zone if(g_bZone[zone][client]) { if(g_mapZones[zone][Type] == ZtStart) - { - CPrintToChat(client, PLUGIN_PREFIX, "Already inside start zone"); return false; - } else if(g_mapZones[zone][Type] == ZtBonusStart) - { - CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus start zone"); return false; - } else if(g_mapZones[zone][Type] == ZtBonus2Start) - { - CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus2 start zone"); return false; - } else if(g_mapZones[zone][Type] == ZtBonus3Start) - { - CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus3 start zone"); return false; - } else if(g_mapZones[zone][Type] == ZtBonus4Start) - { - CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus4 start zone"); return false; - } else if(g_mapZones[zone][Type] == ZtBonus5Start) - { - CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus5 start zone"); return false; - } } - + // Get zone center cords new Float:center[3]; center[0] = (g_mapZones[zone][Point1][0] + g_mapZones[zone][Point2][0]) / 2.0; center[1] = (g_mapZones[zone][Point1][1] + g_mapZones[zone][Point2][1]) / 2.0; - + // Use static height if(g_Settings[UseZoneTeleportZ]) center[2] = g_mapZones[zone][Point1][2] + g_Settings[ZoneTeleportZ]; // Use center height else center[2] = (g_mapZones[zone][Point1][2] + g_mapZones[zone][Point2][2]) / 2.0; - + //If teleporting outside a startzone skip the next end touch output - new bool:touchstart = (Timer_IsPlayerTouchingZoneType(client, ZtStart) || Timer_IsPlayerTouchingZoneType(client, ZtBonusStart) || Timer_IsPlayerTouchingZoneType(client, ZtBonus2Start) || Timer_IsPlayerTouchingZoneType(client, ZtBonus3Start) || Timer_IsPlayerTouchingZoneType(client, ZtBonus4Start) || Timer_IsPlayerTouchingZoneType(client, ZtBonus5Start)); + new bool:touchstart = Timer_IsPlayerTouchingStartZone(client); new bool:targetstart = (g_mapZones[zone][Type] != ZtStart && g_mapZones[zone][Type] != ZtBonusStart && g_mapZones[zone][Type] != ZtBonus2Start && g_mapZones[zone][Type] != ZtBonus3Start && g_mapZones[zone][Type] != ZtBonus4Start && g_mapZones[zone][Type] != ZtBonus5Start); - + if(touchstart && targetstart) Timer_SetIgnoreEndTouchStart(client, 1); - + // Stop speed before and after teleporting if(stopspeed) { @@ -4595,7 +4550,7 @@ stock bool:Tele_Zone(client, zone, bool:stopspeed = true, bool:overwrite_physics CreateTimer(0.0, Timer_StopSpeed, client, TIMER_FLAG_NO_MAPCHANGE); } else TeleportEntity(client, center, NULL_VECTOR, NULL_VECTOR); - + // Anti cheat if(overwrite_physics) { @@ -4603,7 +4558,7 @@ stock bool:Tele_Zone(client, zone, bool:stopspeed = true, bool:overwrite_physics SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", g_Physics[style][StyleTimeScale]); SetEntityGravity(client, g_Physics[style][StyleGravity]); } - + return true; } @@ -4611,12 +4566,12 @@ public Action:Timer_StopSpeed(Handle:timer, any:client) { if(!IsClientInGame(client)) return Plugin_Stop; - + if(!IsPlayerAlive(client)) return Plugin_Stop; - + TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, Float:{0.0,0.0,-100.0}); - + return Plugin_Stop; } @@ -4625,24 +4580,24 @@ public Action:Command_LevelAdminMode(client, args) if (args != 1) { ReplyToCommand(client, "[SM] Usage: sm_zoneadminmode [0/1]"); - return Plugin_Handled; + return Plugin_Handled; } if (args == 1) { decl String:name2[64]; GetCmdArg(1,name2,sizeof(name2)); adminmode = StringToInt(name2); - - if(adminmode == 1) + + if(adminmode == 1) { CPrintToChat(client, PLUGIN_PREFIX, "Adminmode Enabled"); } - else + else { CPrintToChat(client, PLUGIN_PREFIX, "Adminmode Disabled"); } } - return Plugin_Handled; + return Plugin_Handled; } public Action:Command_AddZone(client, args) @@ -4669,7 +4624,7 @@ public Action:Command_LevelName(client, args) if (args != 1) { ReplyToCommand(client, "[SM] Usage: sm_zonename [name]"); - return Plugin_Handled; + return Plugin_Handled; } if (args == 1) { @@ -4677,10 +4632,10 @@ public Action:Command_LevelName(client, args) GetCmdArg(1,name2,sizeof(name2)); decl String:query[256]; FormatEx(query, sizeof(query), "UPDATE mapzone SET name = '%s' WHERE id = %d", name2, g_mapZones[g_iClientLastTrackZone[client]][Id]); - SQL_TQuery(g_hSQL, UpdateLevelCallback, query, client, DBPrio_Normal); + SQL_TQuery(g_hSQL, UpdateLevelCallback, query, client, DBPrio_Normal); PrintToChat(client, "Set LevelName: %s for ZoneID: %d", name2, g_mapZones[g_iClientLastTrackZone[client]][Id]); } - return Plugin_Handled; + return Plugin_Handled; } public Action:Command_LevelID(client, args) @@ -4688,19 +4643,19 @@ public Action:Command_LevelID(client, args) if (args != 1) { ReplyToCommand(client, "[SM] Usage: sm_zoneid [id]"); - return Plugin_Handled; + return Plugin_Handled; } if (args == 1) { decl String:name2[64]; GetCmdArg(1, name2, sizeof(name2)); - + decl String:query2[512]; FormatEx(query2, sizeof(query2), "UPDATE mapzone SET level_id = '%s' WHERE id = %d", name2, g_mapZones[g_iClientLastTrackZone[client]][Id]); - SQL_TQuery(g_hSQL, UpdateLevelCallback, query2, client, DBPrio_Normal); + SQL_TQuery(g_hSQL, UpdateLevelCallback, query2, client, DBPrio_Normal); PrintToChat(client, "Set LevelID: %s for ZoneID: %d", name2, g_mapZones[g_iClientLastTrackZone[client]][Id]); } - return Plugin_Handled; + return Plugin_Handled; } public Action:Command_LevelType(client, args) @@ -4708,19 +4663,19 @@ public Action:Command_LevelType(client, args) if (args != 1) { ReplyToCommand(client, "[SM] Usage: sm_zonetype"); - return Plugin_Handled; + return Plugin_Handled; } if (args == 1) { decl String:name2[64]; GetCmdArg(1, name2, sizeof(name2)); - + decl String:query2[512]; FormatEx(query2, sizeof(query2), "UPDATE mapzone SET type = '%s' WHERE id = %d", name2, g_mapZones[g_iClientLastTrackZone[client]][Id]); - SQL_TQuery(g_hSQL, UpdateLevelCallback, query2, client, DBPrio_Normal); + SQL_TQuery(g_hSQL, UpdateLevelCallback, query2, client, DBPrio_Normal); PrintToChat(client, "Set Type: %s for ZoneID: %d", name2, g_mapZones[g_iClientLastTrackZone[client]][Id]); } - return Plugin_Handled; + return Plugin_Handled; } public UpdateLevelCallback(Handle:owner, Handle:hndl, const String:error[], any:data) @@ -4730,7 +4685,7 @@ public UpdateLevelCallback(Handle:owner, Handle:hndl, const String:error[], any: Timer_LogError("SQL Error on UpdateZone: %s", error); return; } - + LoadMapZones(); } @@ -4738,21 +4693,44 @@ public Action:Command_Stuck(client, args) { if(!g_Settings[StuckEnable]) return Plugin_Handled; - - if(!IsClientInGame(client)) + + if(!IsClientInGame(client)) return Plugin_Handled; - - if(!IsPlayerAlive(client)) + + if(!IsPlayerAlive(client)) return Plugin_Handled; - + + if(Timer_IsPlayerTouchingZoneType(client, ZtStart) || + Timer_IsPlayerTouchingZoneType(client, ZtBonusStart) || + Timer_IsPlayerTouchingZoneType(client, ZtBonus2Start) || + Timer_IsPlayerTouchingZoneType(client, ZtBonus3Start) || + Timer_IsPlayerTouchingZoneType(client, ZtBonus4Start) || + Timer_IsPlayerTouchingZoneType(client, ZtBonus5Start) || + Timer_IsPlayerTouchingZoneType(client, ZtCheckpoint) || + Timer_IsPlayerTouchingZoneType(client, ZtBonusCheckpoint) || + Timer_IsPlayerTouchingZoneType(client, ZtBonus2Checkpoint) || + Timer_IsPlayerTouchingZoneType(client, ZtBonus3Checkpoint) || + Timer_IsPlayerTouchingZoneType(client, ZtBonus4Checkpoint) || + Timer_IsPlayerTouchingZoneType(client, ZtBonus5Checkpoint) || + Timer_IsPlayerTouchingZoneType(client, ZtLevel) || + Timer_IsPlayerTouchingZoneType(client, ZtBonusLevel) || + Timer_IsPlayerTouchingZoneType(client, ZtBonus2Level) || + Timer_IsPlayerTouchingZoneType(client, ZtBonus3Level) || + Timer_IsPlayerTouchingZoneType(client, ZtBonus4Level) || + Timer_IsPlayerTouchingZoneType(client, ZtBonus5Level)) + { + CPrintToChat(client, "%s You can't use this command inside this zone type.", PLUGIN_PREFIX2); + return Plugin_Handled; + } + if(Timer_GetStatus(client) && g_Settings[StuckPenaltyTime] > 0) { Timer_AddPenaltyTime(client, g_Settings[StuckPenaltyTime]); CPrintToChat(client, "%s You have used !stuck and got an %ds penalty time.", PLUGIN_PREFIX2, RoundToFloor(g_Settings[StuckPenaltyTime])); } - + TeleLastCheckpoint(client); - + return Plugin_Handled; } @@ -4760,19 +4738,56 @@ public Action:Command_Restart(client, args) { if(!g_Settings[RestartEnable]) return Plugin_Handled; - - if(!IsClientInGame(client)) + + if(!IsClientInGame(client)) return Plugin_Handled; - + if(Timer_GetMapzoneCount(ZtStart) < 1) return Plugin_Handled; - - if(Timer_IsPlayerTouchingZoneType(client, ZtStart)) + + new track = Timer_GetTrack(client); + + if(track == TRACK_NORMAL && Timer_IsPlayerTouchingZoneType(client, ZtStart)) { - CPrintToChat(client, PLUGIN_PREFIX, "Already inside start zone"); + //CPrintToChat(client, PLUGIN_PREFIX, "Already inside start zone"); return Plugin_Handled; } - + + if(track == TRACK_BONUS && Timer_IsPlayerTouchingZoneType(client, ZtBonusStart)) + { + Timer_SetTrack(client, TRACK_NORMAL); + Client_Start(client); + return Plugin_Handled; + } + + if(track == TRACK_BONUS2 && Timer_IsPlayerTouchingZoneType(client, ZtBonus2Start)) + { + Timer_SetTrack(client, TRACK_NORMAL); + Client_Start(client); + return Plugin_Handled; + } + + if(track == TRACK_BONUS3 && Timer_IsPlayerTouchingZoneType(client, ZtBonus3Start)) + { + Timer_SetTrack(client, TRACK_NORMAL); + Client_Start(client); + return Plugin_Handled; + } + + if(track == TRACK_BONUS4 && Timer_IsPlayerTouchingZoneType(client, ZtBonus4Start)) + { + Timer_SetTrack(client, TRACK_NORMAL); + Client_Start(client); + return Plugin_Handled; + } + + if(track == TRACK_BONUS5 && Timer_IsPlayerTouchingZoneType(client, ZtBonus5Start)) + { + Timer_SetTrack(client, TRACK_NORMAL); + Client_Start(client); + return Plugin_Handled; + } + if(g_timerTeams) { if(Timer_GetChallengeStatus(client) == 1 || Timer_GetCoopStatus(client) == 1) @@ -4781,9 +4796,12 @@ public Action:Command_Restart(client, args) return Plugin_Handled; } } - - Client_Restart(client); - + + if(track == TRACK_NORMAL) + Client_Start(client); + else + Client_BonusRestart(client, track); + return Plugin_Handled; } @@ -4791,11 +4809,11 @@ public Action:Command_Start(client, args) { if(!g_Settings[StartEnable]) return Plugin_Handled; - + decl String:slevel[64]; GetCmdArg(1, slevel, sizeof(slevel)); new level = StringToInt(slevel); - + if(level > 0) { if(g_timerTeams) @@ -4806,18 +4824,18 @@ public Action:Command_Start(client, args) return Plugin_Handled; } } - + Timer_Reset(client); Tele_Level(client, level); return Plugin_Handled; } - - if(!IsClientInGame(client)) + + if(!IsClientInGame(client)) return Plugin_Handled; - + if(Timer_GetMapzoneCount(ZtStart) < 1) return Plugin_Handled; - + if(g_timerTeams) { if(Timer_GetChallengeStatus(client) == 1 || Timer_GetCoopStatus(client) == 1) @@ -4826,9 +4844,9 @@ public Action:Command_Start(client, args) return Plugin_Handled; } } - + Client_Start(client); - + return Plugin_Handled; } @@ -4836,22 +4854,22 @@ public Action:Command_BonusRestart(client, args) { if(!g_Settings[StartEnable]) return Plugin_Handled; - - if(!IsClientInGame(client)) + + if(!IsClientInGame(client)) return Plugin_Handled; - + if(Timer_IsPlayerTouchingZoneType(client, ZtBonusStart)) { - CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus start zone"); + //CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus start zone"); return Plugin_Handled; } - + if(Timer_GetMapzoneCount(ZtBonusStart) < 1) { CPrintToChat(client, PLUGIN_PREFIX, "There is no bonus in this map"); return Plugin_Handled; } - + if(g_timerTeams) { if(Timer_GetChallengeStatus(client) == 1 || Timer_GetCoopStatus(client) == 1) @@ -4860,9 +4878,9 @@ public Action:Command_BonusRestart(client, args) return Plugin_Handled; } } - + Client_BonusRestart(client, TRACK_BONUS); - + return Plugin_Handled; } @@ -4870,22 +4888,22 @@ public Action:Command_Bonus2Restart(client, args) { if(!g_Settings[StartEnable]) return Plugin_Handled; - - if(!IsClientInGame(client)) + + if(!IsClientInGame(client)) return Plugin_Handled; - + if(Timer_IsPlayerTouchingZoneType(client, ZtBonus2Start)) { - CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus2 start zone"); + //CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus2 start zone"); return Plugin_Handled; } - + if(Timer_GetMapzoneCount(ZtBonus2Start) < 1) { CPrintToChat(client, PLUGIN_PREFIX, "There is no bonus2 in this map"); return Plugin_Handled; } - + if(g_timerTeams) { if(Timer_GetChallengeStatus(client) == 1 || Timer_GetCoopStatus(client) == 1) @@ -4894,9 +4912,9 @@ public Action:Command_Bonus2Restart(client, args) return Plugin_Handled; } } - + Client_BonusRestart(client, TRACK_BONUS2); - + return Plugin_Handled; } @@ -4904,22 +4922,22 @@ public Action:Command_Bonus3Restart(client, args) { if(!g_Settings[StartEnable]) return Plugin_Handled; - - if(!IsClientInGame(client)) + + if(!IsClientInGame(client)) return Plugin_Handled; - + if(Timer_IsPlayerTouchingZoneType(client, ZtBonus3Start)) { - CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus3 start zone"); + //CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus3 start zone"); return Plugin_Handled; } - + if(Timer_GetMapzoneCount(ZtBonus3Start) < 1) { CPrintToChat(client, PLUGIN_PREFIX, "There is no bonus3 in this map"); return Plugin_Handled; } - + if(g_timerTeams) { if(Timer_GetChallengeStatus(client) == 1 || Timer_GetCoopStatus(client) == 1) @@ -4928,9 +4946,9 @@ public Action:Command_Bonus3Restart(client, args) return Plugin_Handled; } } - + Client_BonusRestart(client, TRACK_BONUS3); - + return Plugin_Handled; } @@ -4938,22 +4956,22 @@ public Action:Command_Bonus4Restart(client, args) { if(!g_Settings[StartEnable]) return Plugin_Handled; - - if(!IsClientInGame(client)) + + if(!IsClientInGame(client)) return Plugin_Handled; - + if(Timer_IsPlayerTouchingZoneType(client, ZtBonus4Start)) { - CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus4 start zone"); + //CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus4 start zone"); return Plugin_Handled; } - + if(Timer_GetMapzoneCount(ZtBonus4Start) < 1) { CPrintToChat(client, PLUGIN_PREFIX, "There is no bonus4 in this map"); return Plugin_Handled; } - + if(g_timerTeams) { if(Timer_GetChallengeStatus(client) == 1 || Timer_GetCoopStatus(client) == 1) @@ -4962,9 +4980,9 @@ public Action:Command_Bonus4Restart(client, args) return Plugin_Handled; } } - + Client_BonusRestart(client, TRACK_BONUS4); - + return Plugin_Handled; } @@ -4972,22 +4990,22 @@ public Action:Command_Bonus5Restart(client, args) { if(!g_Settings[StartEnable]) return Plugin_Handled; - - if(!IsClientInGame(client)) + + if(!IsClientInGame(client)) return Plugin_Handled; - + if(Timer_IsPlayerTouchingZoneType(client, ZtBonus5Start)) { - CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus5 start zone"); + //CPrintToChat(client, PLUGIN_PREFIX, "Already inside bonus5 start zone"); return Plugin_Handled; } - + if(Timer_GetMapzoneCount(ZtBonus5Start) < 1) { CPrintToChat(client, PLUGIN_PREFIX, "There is no bonus5 in this map"); return Plugin_Handled; } - + if(g_timerTeams) { if(Timer_GetChallengeStatus(client) == 1 || Timer_GetCoopStatus(client) == 1) @@ -4996,36 +5014,47 @@ public Action:Command_Bonus5Restart(client, args) return Plugin_Handled; } } - + Client_BonusRestart(client, TRACK_BONUS5); - + return Plugin_Handled; } +new g_iConfirmTrack[MAXPLAYERS+1]; + ConfirmAbortMenu(client, track) { if (0 < client < MaxClients) { new Handle:menu = CreateMenu(Handle_ConfirmAbortMenu); - + new mate; if(g_timerTeams) mate = Timer_GetClientTeammate(client); - + + SetMenuTitle(menu, "Please confirm your action."); + if(mate > 0) { if(Timer_GetChallengeStatus(client) == 1) - SetMenuTitle(menu, "Are you sure to quit the Challenge?"); + { + AddMenuItem(menu, "no", "Do nothing"); + AddMenuItem(menu, "tele", "Teleport me back"); + AddMenuItem(menu, "unmate", "Cancel challenge"); + } else if(Timer_GetCoopStatus(client) == 1) - SetMenuTitle(menu, "Are you sure to quit the Coop?"); - }else SetMenuTitle(menu, "Are you sure to quit?"); - - decl String:info[8]; - IntToString(track, info, sizeof(info)); - - AddMenuItem(menu, info, "Yes"); - - AddMenuItem(menu, "no", "No"); - + { + AddMenuItem(menu, "no", "Do nothing"); + AddMenuItem(menu, "tele", "Teleport me back"); + AddMenuItem(menu, "unmate", "Cancel partner"); + } + } + else + { + AddMenuItem(menu, "yes", "Yes, Teleport me back"); + AddMenuItem(menu, "no", "No"); + } + + g_iConfirmTrack[client] = track; DisplayMenu(menu, client, 5); } } @@ -5039,11 +5068,16 @@ public Handle_ConfirmAbortMenu(Handle:menu, MenuAction:action, client, itemNum) if(found) { new track = StringToInt(info); - + + if(!StrEqual(info, "no")) + { + + } + if(track == -1) { Client_Restart(client); - + } else if(track == TRACK_NORMAL) { @@ -5059,28 +5093,28 @@ public Handle_ConfirmAbortMenu(Handle:menu, MenuAction:action, client, itemNum) bool:Client_Start(client) { - if(!IsClientInGame(client)) + if(!IsClientInGame(client)) return false; - + //Has player a valid team if(GetClientTeam(client) != CS_TEAM_CT && GetClientTeam(client) != CS_TEAM_T) { new validteam = CS_GetValidSpawnTeam(); - + if(validteam != CS_TEAM_NONE) { CS_SwitchTeam(client, validteam); } - else Timer_LogError("No spawn points for %s", g_currentMap); + else CS_SwitchTeam(client, CS_TEAM_CT); } - + new style = Timer_GetStyle(client); - + //Stop timer Timer_Reset(client); - + //Is player alive - if(!IsPlayerAlive(client)) + if(!IsPlayerAlive(client)) { CS_RespawnPlayer(client); } @@ -5090,39 +5124,39 @@ bool:Client_Start(client) SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", g_Physics[style][StyleTimeScale]); SetEntityGravity(client, g_Physics[style][StyleGravity]); } - + //Teleport player to starzone Tele_Level(client, LEVEL_START); - + return true; } bool:Client_Restart(client, bool:teleport = true) { - if(!IsClientInGame(client)) + if(!IsClientInGame(client)) return false; - + //Has player a valid team if(GetClientTeam(client) != CS_TEAM_CT && GetClientTeam(client) != CS_TEAM_T) { new validteam = CS_GetValidSpawnTeam(); - + if(validteam != CS_TEAM_NONE) { CS_SwitchTeam(client, validteam); } - else Timer_LogError("No spawn points for %s", g_currentMap); + else CS_SwitchTeam(client, CS_TEAM_CT); } - + new style = Timer_GetStyle(client); - + //Stop timer Timer_Reset(client); - + new bool:respawn = true; - + //Is player alive - if(!IsPlayerAlive(client)) + if(!IsPlayerAlive(client)) { CS_RespawnPlayer(client); respawn = false; @@ -5133,45 +5167,45 @@ bool:Client_Restart(client, bool:teleport = true) SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", g_Physics[style][StyleTimeScale]); SetEntityGravity(client, g_Physics[style][StyleGravity]); } - + //Teleport player to starzone if(g_Settings[TeleportOnRestart] && teleport) { Tele_Level(client, LEVEL_START); - } + } //Or just respawn him else if(respawn) { CS_RespawnPlayer(client); } - + return true; } bool:Client_BonusRestart(client, track) { - if(!IsClientInGame(client)) + if(!IsClientInGame(client)) return false; - + //Has player a valid team if(GetClientTeam(client) != CS_TEAM_CT && GetClientTeam(client) != CS_TEAM_T) { new validteam = CS_GetValidSpawnTeam(); - + if(validteam != CS_TEAM_NONE) { CS_SwitchTeam(client, validteam); } else Timer_LogError("No spawn points for %s", g_currentMap); } - + new style = Timer_GetStyle(client); - + //Stop timer Timer_Reset(client); - + //Is player alive - if(!IsPlayerAlive(client)) + if(!IsPlayerAlive(client)) { CS_RespawnPlayer(client); } @@ -5181,7 +5215,7 @@ bool:Client_BonusRestart(client, track) SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", g_Physics[style][StyleTimeScale]); SetEntityGravity(client, g_Physics[style][StyleGravity]); } - + //Teleport player to bonus-starzone if(track == TRACK_BONUS) return Tele_Level(client, LEVEL_BONUS_START); @@ -5193,7 +5227,7 @@ bool:Client_BonusRestart(client, track) return Tele_Level(client, LEVEL_BONUS4_START); else if(track == TRACK_BONUS5) return Tele_Level(client, LEVEL_BONUS5_START); - + return true; } @@ -5207,17 +5241,17 @@ AdminZoneTeleport(client) { new Handle:menu = CreateMenu(MenuHandlerAdminZone); SetMenuTitle(menu, "Zone Selection"); - + for (new zone = 0; zone < g_mapZonesCount; zone++) { decl String:zone_name[32]; FormatEx(zone_name, sizeof(zone_name), "%s", g_mapZones[zone][zName]); - + decl String:zone_id[32]; FormatEx(zone_id,sizeof(zone_id), "%d", zone); AddMenuItem(menu, zone_id, zone_name); } - + SetMenuExitButton(menu, true); DisplayMenu(menu, client, MENU_TIME_FOREVER); } @@ -5247,17 +5281,17 @@ AdminZoneDelete(client) { new Handle:menu = CreateMenu(MenuHandlerAdminZoneDelete); SetMenuTitle(menu, "Zone Selection"); - + for (new zone = 0; zone < g_mapZonesCount; zone++) { decl String:zone_name[32]; FormatEx(zone_name, sizeof(zone_name), "%s", g_mapZones[zone][zName]); - + decl String:zone_id[32]; FormatEx(zone_id,sizeof(zone_id), "%d", zone); AddMenuItem(menu, zone_id, zone_name); } - + SetMenuExitButton(menu, true); DisplayMenu(menu, client, MENU_TIME_FOREVER); } @@ -5273,7 +5307,7 @@ public MenuHandlerAdminZoneDelete(Handle:menu, MenuAction:action, client, param2 { decl String:query[64]; FormatEx(query, sizeof(query), "DELETE FROM mapzone WHERE id = %d", g_mapZones[zone][Id]); - + SQL_TQuery(g_hSQL, DeleteMapZoneCallback, query, client, DBPrio_Normal); } } @@ -5287,7 +5321,7 @@ public Action:Command_Levels(client, args) decl String:slevel[64]; GetCmdArg(1, slevel, sizeof(slevel)); new level = StringToInt(slevel); - + if(level > 0) { if(g_timerTeams) @@ -5298,33 +5332,33 @@ public Action:Command_Levels(client, args) return Plugin_Handled; } } - + Timer_Reset(client); Tele_Level(client, level); return Plugin_Handled; } - + new Handle:menu = CreateMenu(MenuHandlerLevels); SetMenuTitle(menu, "Stage Teleport Selection"); - + for (new zone = 0; zone < g_mapZonesCount; zone++) { if(g_mapZones[zone][Level_Id] < 1) { continue; } - + decl String:zone_name[32]; FormatEx(zone_name, sizeof(zone_name), "%s", g_mapZones[zone][zName]); - + decl String:zone_id[32]; FormatEx(zone_id,sizeof(zone_id), "%d", zone); AddMenuItem(menu, zone_id, zone_name); } - + SetMenuExitButton(menu, true); DisplayMenu(menu, client, 20); - + return Plugin_Handled; } @@ -5347,20 +5381,20 @@ public Native_AddMapZone(Handle:plugin, numParams) { decl String:map[32]; GetNativeString(1, map, sizeof(map)); - - new MapZoneType:type = GetNativeCell(2); - + + new MapZoneType:type = GetNativeCell(2); + decl String:name[32]; GetNativeString(1, name, sizeof(name)); - + new level_id = GetNativeCell(2); - + new Float:point1[3]; GetNativeArray(3, point1, sizeof(point1)); - + new Float:point2[3]; GetNativeArray(3, point2, sizeof(point2)); - + AddMapZone(map, type, name, level_id, point1, point2); } @@ -5392,10 +5426,10 @@ public Native_GetClientLevelID(Handle:plugin, numParams) public Native_GetLevelName(Handle:plugin, numParams) { new id = GetNativeCell(1); - new nlen = GetNativeCell(3); + new nlen = GetNativeCell(3); if (nlen <= 0) return false; - + for (new i = 0; i < g_mapZonesCount; i++) { if(g_mapZones[i][Level_Id] == id) @@ -5406,7 +5440,7 @@ public Native_GetLevelName(Handle:plugin, numParams) return true; } } - + return false; } @@ -5436,7 +5470,7 @@ public Native_IsPlayerTouchingZoneType(Handle:plugin, numParams) { new client = GetNativeCell(1); new MapZoneType:type = GetNativeCell(2); - + return IsPlayerTouchingZoneType(client, type); } @@ -5446,18 +5480,18 @@ IsPlayerTouchingZoneType(client, MapZoneType:type) { if(g_mapZones[i][Type] != type) continue; - + if(g_bZone[i][client]) return 1; } - + return 0; } public Native_GetMapzoneCount(Handle:plugin, numParams) { new MapZoneType:type = GetNativeCell(1); - + new count = 0; if(type == ZtLevel || type == ZtBonusLevel) @@ -5470,11 +5504,11 @@ public Native_GetMapzoneCount(Handle:plugin, numParams) LevelID[mapZone] = g_mapZones[mapZone][Level_Id]; } } - + SortIntegers(LevelID, g_mapZonesCount, Sort_Ascending); - + new lastlevel; - + for (new mapZone = 0; mapZone < g_mapZonesCount; mapZone++) { if (LevelID[mapZone] > lastlevel) @@ -5494,13 +5528,13 @@ public Native_GetMapzoneCount(Handle:plugin, numParams) } } } - + return count; } public bool:FilterOnlyPlayers(entity, contentsMask, any:data) { - if(entity != data && entity > 0 && entity <= MaxClients) + if(entity != data && entity > 0 && entity <= MaxClients) return true; return false; } @@ -5533,19 +5567,19 @@ public Action:Hook_NormalSound(clients[64], &numClients, String:sample[PLATFORM_ if (g_Settings[DisableDoorSounds]) if (StrContains(sample, "door") != -1) return Plugin_Stop; - + if (g_Settings[DisableButtonSounds]) if (StrContains(sample, "button") != -1) return Plugin_Stop; - + return Plugin_Continue; } public Action:Command_ToggleTeleporters(client, args) { ToggleTeleporters(client); - - return Plugin_Handled; + + return Plugin_Handled; } stock ToggleTeleporters(client) @@ -5553,12 +5587,12 @@ stock ToggleTeleporters(client) if(g_bTeleportersDisabled) { g_bTeleportersDisabled = false; - + ReplyToCommand(client, "(Re-)Enabled all trigger_teleport entitys"); - + new entity; decl String:targetname[256]; - + while ((entity = FindEntityByClassname(entity, "info_teleport_destination")) != -1) { GetEntPropString(entity, Prop_Data, "m_iName", targetname, sizeof(targetname)); @@ -5569,12 +5603,12 @@ stock ToggleTeleporters(client) else { g_bTeleportersDisabled = true; - + ReplyToCommand(client, "Disabled all trigger_teleport entitys"); - + new entity; decl String:targetname[256]; - + while ((entity = FindEntityByClassname(entity, "info_teleport_destination")) != -1) { GetEntPropString(entity, Prop_Data, "m_iName", targetname, sizeof(targetname)); @@ -5597,13 +5631,13 @@ stock FixAngRotation() { new Float:ang[3]; GetEntPropVector(entity, Prop_Send, "m_angRotation", ang); - + if(ang[0] > 360.0 || ang[1] > 360.0 || ang[2] > 360.0 || ang[0] < -360.0 || ang[1] < -360.0 || ang[2] < -360.0) { ang[0] = float(RoundToFloor(ang[0]) % 60); ang[1] = float(RoundToFloor(ang[1]) % 60); ang[2] = float(RoundToFloor(ang[2]) % 60); - + SetEntPropVector(entity, Prop_Send, "m_angRotation", ang); } } diff --git a/gameserver/addons/sourcemod/scripting/timer-mapzones_startzone_nojump.sp b/gameserver/addons/sourcemod/scripting/timer-mapzones_startzone_nojump.sp index 7a4dc56..6e61faf 100644 --- a/gameserver/addons/sourcemod/scripting/timer-mapzones_startzone_nojump.sp +++ b/gameserver/addons/sourcemod/scripting/timer-mapzones_startzone_nojump.sp @@ -1,11 +1,13 @@ #pragma semicolon 1 - + #include #include #include #include #include - +#include +#include + public Plugin:myinfo = { name = "[Timer] Start zone no jump", @@ -17,14 +19,25 @@ public Plugin:myinfo = public OnPluginStart() { + LoadPhysics(); + LoadTimerSettings(); HookEvent("player_jump", Event_PlayerJump); } +public OnMapStart() +{ + LoadPhysics(); + LoadTimerSettings(); +} + public Action:Event_PlayerJump(Handle:event, const String:name[], bool:dontBroadcast) { new client = GetClientOfUserId(GetEventInt(event, "userid")); - if(Timer_IsPlayerTouchingZoneType(client, ZtStart) || Timer_IsPlayerTouchingZoneType(client, ZtBonusStart)) + if(!g_Physics[Timer_GetStyle(client)][StyleStartZoneAntiBhop]) + return Plugin_Continue; + + if(Timer_IsPlayerTouchingZoneType(client, ZtStart) || Timer_IsPlayerTouchingZoneType(client, ZtBonusStart) || Timer_IsPlayerTouchingZoneType(client, ZtBonus2Start) || Timer_IsPlayerTouchingZoneType(client, ZtBonus3Start) || Timer_IsPlayerTouchingZoneType(client, ZtBonus4Start) || Timer_IsPlayerTouchingZoneType(client, ZtBonus5Start)) { CreateTimer(0.05, DelayedSlowDown, client); } @@ -45,8 +58,8 @@ public OnClientEndTouchZoneType(client, MapZoneType:type) if(type == ZtStart || type == ZtBonusStart) { new bool:onground = bool:(GetEntityFlags(client) & FL_ONGROUND); - - if(!onground) + + if(!onground && g_Physics[Timer_GetStyle(client)][StyleStartZoneAntiBhop]) { CheckVelocity(client, 1, 120.0); } diff --git a/gameserver/addons/sourcemod/scripting/timer-menu.sp b/gameserver/addons/sourcemod/scripting/timer-menu.sp index bcd420a..fd366f1 100644 --- a/gameserver/addons/sourcemod/scripting/timer-menu.sp +++ b/gameserver/addons/sourcemod/scripting/timer-menu.sp @@ -20,12 +20,12 @@ public OnPluginStart() { LoadPhysics(); LoadTimerSettings(); - - RegConsoleCmd("sm_menu", Command_Menu); + + RegConsoleCmd("sm_menu", Command_Menu); RegConsoleCmd("sm_timer", Command_HelpMenu); RegConsoleCmd("sm_help", Command_HelpMenu); RegConsoleCmd("sm_commands", Command_HelpMenu); - + mod = GetGameMod(); } @@ -33,14 +33,14 @@ public OnMapStart() { LoadPhysics(); LoadTimerSettings(); - + GetCurrentMap(g_sCurrentMap, sizeof(g_sCurrentMap)); } public Action:Command_Menu(client, args) { Menu(client); - + return Plugin_Handled; } @@ -62,14 +62,14 @@ public Action:Command_HelpMenu(client, args) Init_Commands(); g_iCurrentPage[client] = 1; CommandPanel(client); - + return Plugin_Handled; } public Init_Commands() { g_iCmdCount = 0; - + Add_Command("!timer - Displays this menu", "timer-core.smx"); Add_Command("!menu - Displays a main menu", "timer-menu.smx"); Add_Command("!style - Displays style selection menu", "timer-physics.smx"); @@ -115,7 +115,7 @@ public Init_Commands() Add_Command("!ljpopup - Toogle Long Jump Stats Popup", "timer-ljstats.smx"); Add_Command("!ljblock - Register Long Jump Destination", "timer-ljstats.smx"); Add_Command("!gap - Measure units between 2 point", "timer-ljstats.smx"); - + Add_Command("!credits - Displays Credits", "timer-core.smx"); } @@ -133,16 +133,16 @@ Add_Command(String:info[], String:plugin[], bool:enable = true) public CommandPanel(client) { new firstcomand = g_iCurrentPage[client]*commandsperpage-commandsperpage; - + new Handle:panel = CreatePanel(); SetPanelTitle(panel, ">>> Timer Help Menu <<<\nby Zipcore"); - + new String:sPage[512]; Format(sPage, sizeof(sPage), " -- Page %d/%d --", g_iCurrentPage[client], maxpage); - + DrawPanelText(panel, sPage); DrawPanelText(panel, " "); - + new String:buffer[512]; new iCmdCount; for(new i=firstcomand; i < (g_iCurrentPage[client]*commandsperpage); i++) @@ -151,24 +151,26 @@ public CommandPanel(client) DrawPanelText(panel, buffer); iCmdCount++; } - + DrawPanelText(panel, " "); - - + + new startkey = 8; if(g_iCurrentPage[client] > 1) startkey = 7; - + //Fix CS:GO menu buttons if(mod == MOD_CSGO) SetPanelCurrentKey(panel, startkey); else SetPanelCurrentKey(panel, startkey+1); - + if(g_iCurrentPage[client] > 1) DrawPanelItem(panel, "- Back -"); else DrawPanelText(panel, " "); if(g_iCurrentPage[client] < maxpage) DrawPanelItem(panel, "- Next -"); else DrawPanelText(panel, " "); + + SetPanelCurrentKey(panel, 9); DrawPanelItem(panel, "- Exit -"); - + SendPanelToClient(panel, client, CommandPanelHandler, MENU_TIME_FOREVER); CloseHandle(panel); @@ -178,7 +180,7 @@ public CommandPanelHandler (Handle:menu, MenuAction:action,client, param2) { if ( action == MenuAction_Select ) { - if(mod == MOD_CSGO) + if(mod == MOD_CSGO) { switch (param2) { @@ -222,9 +224,9 @@ Menu(client) if (0 < client < MaxClients) { new Handle:menu = CreateMenu(Handle_Menu); - SetMenuTitle(menu, "Timer - Main Menu \nby Zipcore"); - - AddMenuItem(menu, "mode", "Change Style"); + SetMenuTitle(menu, "Timer - Main Menu \nby Zipcore"); + + AddMenuItem(menu, "mode", "Change Style"); if(PluginEnabled("timer-physicsinfo.smx")) { AddMenuItem(menu, "info", "Mode Settings Info"); @@ -243,11 +245,11 @@ Menu(client) AddMenuItem(menu, "hud", "Custom HUD Settings"); } AddMenuItem(menu, "credits", "Credits"); - + DisplayMenu(menu, client, MENU_TIME_FOREVER); } } - + public Handle_Menu(Handle:menu, MenuAction:action, client, itemNum) { if ( action == MenuAction_Select ) @@ -274,11 +276,11 @@ public Handle_Menu(Handle:menu, MenuAction:action, client, itemNum) } else if(StrEqual(info, "challenge")) { - if(IsClientInGame(client)) FakeClientCommand(client, "sm_challenge"); + if(IsClientInGame(client)) FakeClientCommand(client, "sm_challenge"); } else if(StrEqual(info, "hud")) { - if(IsClientInGame(client)) FakeClientCommand(client, "sm_hud"); + if(IsClientInGame(client)) FakeClientCommand(client, "sm_hud"); } else if(StrEqual(info, "credits")) { @@ -293,18 +295,18 @@ WorldRecordMenu(client) if (0 < client < MaxClients) { new Handle:menu = CreateMenu(Handle_WorldRecordMenu); - + SetMenuTitle(menu, "World Record Menu"); - + AddMenuItem(menu, "wr", "World Record"); AddMenuItem(menu, "bwr", "Bonus World Record"); AddMenuItem(menu, "swr", "Short World Record"); AddMenuItem(menu, "main", "Back"); - + DisplayMenu(menu, client, MENU_TIME_FOREVER); } } - + public Handle_WorldRecordMenu(Handle:menu, MenuAction:action, client, itemNum) { if ( action == MenuAction_Select ) @@ -338,9 +340,9 @@ TeleportMenu(client) if (0 < client < MaxClients) { new Handle:menu = CreateMenu(Handle_TeleportMenu); - + SetMenuTitle(menu, "Teleport Menu"); - + if(g_Settings[PlayerTeleportEnable]) { AddMenuItem(menu, "teleme", "Teleport to Player"); @@ -354,11 +356,11 @@ TeleportMenu(client) AddMenuItem(menu, "checkpoint", "Teleport to Checkpoint"); } AddMenuItem(menu, "main", "Back"); - + DisplayMenu(menu, client, MENU_TIME_FOREVER); } } - + public Handle_TeleportMenu(Handle:menu, MenuAction:action, client, itemNum) { if ( action == MenuAction_Select ) diff --git a/gameserver/addons/sourcemod/scripting/timer-mysql.sp b/gameserver/addons/sourcemod/scripting/timer-mysql.sp index 21df738..c3ec251 100644 --- a/gameserver/addons/sourcemod/scripting/timer-mysql.sp +++ b/gameserver/addons/sourcemod/scripting/timer-mysql.sp @@ -32,7 +32,7 @@ public Plugin:myinfo = public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) { RegPluginLibrary("timer-mysql"); - + CreateNative("Timer_SqlGetConnection", Native_SqlGetConnection); return APLRes_Success; @@ -42,9 +42,9 @@ public OnPluginStart() { g_timerOnTimerSqlConnected = CreateGlobalForward("OnTimerSqlConnected", ET_Event, Param_Cell); g_timerOnTimerSqlStop = CreateGlobalForward("OnTimerSqlStop", ET_Event); - + RegAdminCmd("timer_sql_force_update", Command_ForceUpdate, ADMFLAG_RCON, "timer_sql_force_update "); - + ConnectSQL(); } @@ -58,8 +58,8 @@ public Action:Command_ForceUpdate(client, args) InstallUpdates(); } else strcopy(g_DB_Version, sizeof(g_DB_Version), "2.1.3"); - - return Plugin_Handled; + + return Plugin_Handled; } public OnPluginEnd() @@ -72,17 +72,17 @@ public OnPluginEnd() ConnectSQL() { g_DatabaseReady = false; - + if(g_hSQL != INVALID_HANDLE) { Call_StartForward(g_timerOnTimerSqlStop); Call_Finish(); - + CloseHandle(g_hSQL); } - + g_hSQL = INVALID_HANDLE; - + if (SQL_CheckConfig("timer")) { SQL_TConnect(ConnectSQLCallback, "timer"); @@ -104,21 +104,21 @@ public ConnectSQLCallback(Handle:owner, Handle:hndl, const String:error[], any:d if (hndl == INVALID_HANDLE) { g_reconnectCounter++; - + Timer_LogError("[timer-mysql.smx] Connection to SQL database has failed, Try %d, Reason: %s", g_reconnectCounter, error); - - if(g_reconnectCounter >= 100) + + if(g_reconnectCounter >= 100) { Call_StartForward(g_timerOnTimerSqlStop); Call_Finish(); Timer_LogError("[timer-mysql.smx] +++ To much errors. Restart your server for a new try. +++"); } - else if(g_reconnectCounter > 5) + else if(g_reconnectCounter > 5) CreateTimer(5.0, Timer_ReConnect); else if(g_reconnectCounter > 3) CreateTimer(3.0, Timer_ReConnect); else CreateTimer(1.0, Timer_ReConnect); - + return; } @@ -126,7 +126,7 @@ public ConnectSQLCallback(Handle:owner, Handle:hndl, const String:error[], any:d SQL_GetDriverIdent(owner, driver, sizeof(driver)); g_hSQL = CloneHandle(hndl); - + if (StrEqual(driver, "mysql", false)) { SQL_SetCharset(g_hSQL, "utf8"); @@ -138,7 +138,7 @@ public ConnectSQLCallback(Handle:owner, Handle:hndl, const String:error[], any:d Call_Finish(); Timer_LogError("##### Timer ERROR: SqLite is not supported, please check you databases.cfg and use MySQL driver #####"); } - + g_reconnectCounter = 1; } @@ -152,14 +152,14 @@ public CreateSQLTableCallback(Handle:owner, Handle:hndl, const String:error[], a return; } - + if (hndl == INVALID_HANDLE) { Timer_LogError("[timer-mysql.smx] SQL Error on CreateSQLTableCallback: %s", error); ConnectSQL(); return; } - + SQL_TQuery(g_hSQL, GetDBVersionCallback, "SELECT `setting` FROM `settings` WHERE `key` = \"db_version\";"); } @@ -171,42 +171,42 @@ public GetDBVersionCallback(Handle:owner, Handle:hndl, const String:error[], any ConnectSQL(); return; } - + if (hndl == INVALID_HANDLE) { Timer_LogError("[timer-mysql.smx] SQL Error on GetDBVersionCallback: %s", error); ConnectSQL(); return; } - + // Existing database if(SQL_FetchRow(hndl)) { SQL_FetchString(hndl, 0, g_DB_Version, sizeof(g_DB_Version)); - + // Database up to date if(StrEqual(g_DB_Version, g_Version, true)) { g_DatabaseReady = true; } - + /// Database outdated else if(CheckVersionOutdated(g_DB_Version, g_Version)) InstallUpdates(); - + // Plugin outdated else Timer_LogError("[timer-mysql.smx] Database v%s is newer then Plugin v%s", g_DB_Version, g_Version); } // Install new database else InstallNew(); - + if(g_DatabaseReady) { Timer_LogInfo("[timer-mysql.smx] MySQL v%s connection established and ready.", g_DB_Version); Call_StartForward(g_timerOnTimerSqlConnected); Call_PushCell(_:g_hSQL); Call_Finish(); - + CreateTimer(1.0, Timer_HeartBeat, _, TIMER_REPEAT); } } @@ -215,10 +215,10 @@ stock CheckVersionOutdated(String:version_old[], String:version_new[]) { decl String:versions_old[4][32]; ExplodeString(version_old, ".", versions_old, 4, 32); - + decl String:versions_new[4][32]; ExplodeString(version_new, ".", versions_new, 4, 32); - + for (new i = 0; i < 4; i++) { if(StringToInt(versions_old[i]) < StringToInt(versions_new[i])) @@ -226,7 +226,7 @@ stock CheckVersionOutdated(String:version_old[], String:version_new[]) else if(StringToInt(versions_old[i]) > StringToInt(versions_new[i])) return false; } - + return false; } @@ -238,7 +238,7 @@ public EmptyCallback(Handle:owner, Handle:hndl, const String:error[], any:data) ConnectSQL(); return; } - + if (hndl == INVALID_HANDLE) { Timer_LogError("SQL Error on EmptyCallback: %s", error); @@ -256,7 +256,7 @@ public Action:Timer_HeartBeat(Handle:timer, any:data) Call_StartForward(g_timerOnTimerSqlStop); Call_Finish(); } - + return Plugin_Continue; } @@ -271,126 +271,126 @@ stock InstallNew() { decl String:date[32]; FormatTime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", GetTime()); - + Timer_LogInfo("[timer-mysql.smx] No existing settings table found."); Timer_LogInfo("[timer-mysql.smx] MySQL connection installed with version %s.", g_Version); - + decl String:query[2048]; - + Format(query, sizeof(query), "INSERT INTO `settings`(`key`, `setting`) VALUES ('db_version', '%s');", g_Version); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - + Format(query, sizeof(query), "INSERT INTO `settings`(`key`, `setting`) VALUES ('setup', '%s');", date); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - + Format(query, sizeof(query), "INSERT INTO `settings`(`key`, `setting`) VALUES ('last_update', '%s');", date); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - - /* Create ROUND table */ - Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS `round` (`id` int(11) NOT NULL AUTO_INCREMENT, `map` varchar(32) NOT NULL, `auth` varchar(32) NOT NULL, `time` float NOT NULL, `jumps` int(11) NOT NULL, `style` int(11) NOT NULL, `track` int(11) NOT NULL, `name` varchar(64) NOT NULL, `finishcount` int(11) NOT NULL, `stage` int(11) NOT NULL, `fpsmax` int(11) NOT NULL, `jumpacc` float NOT NULL, `strafes` int(11) NOT NULL, `strafeacc` float NOT NULL, `avgspeed` float NOT NULL, `maxspeed` float NOT NULL, `finishspeed` float NOT NULL, `flashbangcount` int(11) NULL, `rank` int(11) NOT NULL, `replaypath` varchar(32) NOT NULL, `custom1` varchar(32) NULL, `custom2` varchar(32) NULL, `custom3` varchar(32) NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `single_record` (`auth`, `map`, `style`, `track`));"); + + /* Create ROUND table */ + Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS `round` (`id` int(11) NOT NULL AUTO_INCREMENT, `map` varchar(32) NOT NULL, `auth` varchar(32) NOT NULL, `time` float NOT NULL, `jumps` int(11) NOT NULL, `style` int(11) NOT NULL, `track` int(11) NOT NULL, `name` varchar(64) NOT NULL, `finishcount` int(11) NOT NULL, `stage` int(11) NOT NULL, `fpsmax` int(11) NOT NULL, `jumpacc` float NOT NULL, `strafes` int(11) NOT NULL, `strafeacc` float NOT NULL, `avgspeed` float NOT NULL, `maxspeed` float NOT NULL, `finishspeed` float NOT NULL, `flashbangcount` int(11) NULL, `rank` int(11) NOT NULL, `replaypath` varchar(32) NOT NULL, `custom1` varchar(32) NULL, `custom2` varchar(32) NULL, `custom3` varchar(32) NULL, date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `single_record` (`auth`, `map`, `style`, `track`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - - /* Create MAPZONE table */ - Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS `mapzone` (`id` int(11) NOT NULL AUTO_INCREMENT, `type` int(11) NOT NULL, `level_id` int(11) NOT NULL, `point1_x` float NOT NULL, `point1_y` float NOT NULL, `point1_z` float NOT NULL, `point2_x` float NOT NULL, `point2_y` float NOT NULL, `point2_z` float NOT NULL, `map` varchar(64) NOT NULL, `name` varchar(32) NOT NULL, PRIMARY KEY (`id`));"); + + /* Create MAPZONE table */ + Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS `mapzone` (`id` int(11) NOT NULL AUTO_INCREMENT, `type` int(11) NOT NULL, `level_id` int(11) NOT NULL, `point1_x` float NOT NULL, `point1_y` float NOT NULL, `point1_z` float NOT NULL, `point2_x` float NOT NULL, `point2_y` float NOT NULL, `point2_z` float NOT NULL, `map` varchar(64) NOT NULL, `name` varchar(32) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - - /* Create MAPTIER table */ - Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS `maptier` (`id` int(11) NOT NULL AUTO_INCREMENT, `map` varchar(32) NOT NULL, `track` int(11) NOT NULL, `tier` int(11) NOT NULL, `stagecount` int(11) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `single_record` (`map`, `track`));"); + + /* Create MAPTIER table */ + Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS `maptier` (`id` int(11) NOT NULL AUTO_INCREMENT, `map` varchar(32) NOT NULL, `track` int(11) NOT NULL, `tier` int(11) NOT NULL, `stagecount` int(11) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `single_record` (`map`, `track`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - - /* Create RANKS table */ - Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS `ranks` (`auth` varchar(24) NOT NULL PRIMARY KEY, `points` int(11) NOT NULL default 0, `lastname` varchar(65) NOT NULL default '', `lastplay` int(11) NOT NULL default 0);"); + + /* Create RANKS table */ + Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS `ranks` (`auth` varchar(24) NOT NULL PRIMARY KEY, `points` int(11) NOT NULL default 0, `lastname` varchar(65) NOT NULL default '', `lastplay` int(11) NOT NULL default 0) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - + g_DatabaseReady = true; } stock InstallUpdates() { decl String:update_version[32]; - + decl String:query[2048]; - + Timer_LogInfo("[timer-mysql.smx] ############################################################"); Timer_LogInfo("[timer-mysql.smx] MySQL v%s is outdated.", g_DB_Version); - + Format(update_version, sizeof(update_version), "2.1.4.7"); if(CheckVersionOutdated(g_DB_Version, update_version)) { Timer_LogError("[timer-mysql.smx] Executing updates for v%s: Levelprocess fix", update_version); - + Format(query, sizeof(query), "UPDATE `round` SET `levelprocess` = 999 WHERE `bonus` = 0 AND `levelprocess` < 1;"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - + Format(query, sizeof(query), "UPDATE `round` SET `levelprocess` = 1999 WHERE `bonus` = 1 AND `levelprocess` < 1;"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - + Format(query, sizeof(query), "UPDATE `round` SET `levelprocess` = 500 WHERE `bonus` = 2 AND `levelprocess` < 1;"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - + Timer_LogInfo("[timer-mysql.smx] Executing updates for v%s: Bonus start fix", update_version); - + Format(query, sizeof(query), "UPDATE mapzone SET level_id = 1001 WHERE level_id = 1000"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); } - + Format(update_version, sizeof(update_version), "2.1.5.1"); if(CheckVersionOutdated(g_DB_Version, update_version)) { Timer_LogError("[timer-mysql.smx] Executing updates for v%s: Flashbangcount fix", update_version); - + // flashbangcount fix Format(query, sizeof(query), "ALTER TABLE `round` MODIFY `flashbangcount` DEFAULT 0;"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - + Format(query, sizeof(query), "UPDATE `round` SET `flashbangcount` = 0 WHERE `flashbangcount` < 1;"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); } - - + + Format(update_version, sizeof(update_version), "2.2.0.0"); if(CheckVersionOutdated(g_DB_Version, update_version)) { Timer_LogError("[timer-mysql.smx] Executing updates for v%s: Major update mysql module fix", update_version); - + // Rename bonus to track Format(query, sizeof(query), "ALTER TABLE round CHANGE bonus track int(11);"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - + Format(query, sizeof(query), "ALTER TABLE maptier CHANGE bonus track int(11);"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - + // Rename physicsdifficulty to style Format(query, sizeof(query), "ALTER TABLE round CHANGE physicsdifficulty style int(11);"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - + // Rename levelprocess to stage Format(query, sizeof(query), "ALTER TABLE round CHANGE levelprocess stage int(11);"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); } - + Format(update_version, sizeof(update_version), "2.2.1.1"); if(CheckVersionOutdated(g_DB_Version, update_version)) { Timer_LogError("[timer-mysql.smx] Executing updates for v%s: Custom field default fix", update_version); - + // custom field default fix Format(query, sizeof(query), "ALTER TABLE `round` MODIFY `custom1` DEFAULT 0;"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); @@ -402,12 +402,12 @@ stock InstallUpdates() Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); } - + Format(update_version, sizeof(update_version), "2.3.0.2"); if(CheckVersionOutdated(g_DB_Version, update_version)) { Timer_LogError("[timer-mysql.smx] Executing updates for v%s: Custom field default fix", update_version); - + // collation fix Format(query, sizeof(query), "alter table maptier convert to character set utf8 collate utf8_general_ci;"); Timer_LogInfo("[timer-mysql.smx] Query: %s", query); @@ -431,16 +431,16 @@ stock InstallUpdates() Timer_LogInfo("[timer-mysql.smx] Query: %s", query); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); } - + decl String:date[32]; FormatTime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", GetTime()); Format(query, sizeof(query), "UPDATE `settings` SET `setting` = \"%s\" WHERE `key` = \"last_update\";", date); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); - + Format(query, sizeof(query), "UPDATE `settings` SET `setting` = \"%s\" WHERE `key` = \"db_version\";", g_Version); SQL_TQuery(g_hSQL, EmptyCallback, query, _, DBPrio_High); Timer_LogInfo("[timer-mysql.smx] MySQL v%s version updated.", g_Version); Timer_LogInfo("[timer-mysql.smx] ############################################################"); - + g_DatabaseReady = true; } diff --git a/gameserver/addons/sourcemod/scripting/timer-nominations.sp b/gameserver/addons/sourcemod/scripting/timer-nominations.sp new file mode 100644 index 0000000..8f1f840 --- /dev/null +++ b/gameserver/addons/sourcemod/scripting/timer-nominations.sp @@ -0,0 +1,550 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * Nominations Extended + * Allows players to nominate maps for Mapchooser + * + * Nominations Extended (C)2012-2013 Powerlord (Ross Bemrose) + * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#include +#include +#include +#include +#include +#include +#pragma semicolon 1 + +#define MCE_VERSION "1.10.0" + +public Plugin:myinfo = +{ + name = "Map Nominations Extended", + author = "Powerlord and AlliedModders LLC", + description = "Provides Map Nominations", + version = MCE_VERSION, + url = "https://forums.alliedmods.net/showthread.php?t=156974" +}; + +new Handle:g_Cvar_ExcludeOld = INVALID_HANDLE; +new Handle:g_Cvar_ExcludeCurrent = INVALID_HANDLE; + +new Handle:g_MapList = INVALID_HANDLE; +new Handle:g_MapMenu = INVALID_HANDLE; +new g_mapFileSerial = -1; + +#define MAPSTATUS_ENABLED (1<<0) +#define MAPSTATUS_DISABLED (1<<1) +#define MAPSTATUS_EXCLUDE_CURRENT (1<<2) +#define MAPSTATUS_EXCLUDE_PREVIOUS (1<<3) +#define MAPSTATUS_EXCLUDE_NOMINATED (1<<4) + +new Handle:g_mapTrie; + +// Nominations Extended Convars +new Handle:g_Cvar_MarkCustomMaps = INVALID_HANDLE; + +public OnPluginStart() +{ + LoadTranslations("common.phrases"); + LoadTranslations("nominations.phrases"); + LoadTranslations("basetriggers.phrases"); // for Next Map phrase + LoadTranslations("mapchooser_extended.phrases"); + + new arraySize = ByteCountToCells(PLATFORM_MAX_PATH); + g_MapList = CreateArray(arraySize); + + g_Cvar_ExcludeOld = CreateConVar("sm_nominate_excludeold", "1", "Specifies if the current map should be excluded from the Nominations list", 0, true, 0.00, true, 1.0); + g_Cvar_ExcludeCurrent = CreateConVar("sm_nominate_excludecurrent", "1", "Specifies if the MapChooser excluded maps should also be excluded from Nominations", 0, true, 0.00, true, 1.0); + + RegConsoleCmd("say", Command_Say); + RegConsoleCmd("say_team", Command_Say); + + RegConsoleCmd("sm_nominate", Command_Nominate); + + RegAdminCmd("sm_nominate_addmap", Command_Addmap, ADMFLAG_CHANGEMAP, "sm_nominate_addmap - Forces a map to be on the next mapvote."); + + // Nominations Extended cvars + CreateConVar("ne_version", MCE_VERSION, "Nominations Extended Version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_NOTIFY|FCVAR_DONTRECORD); + + + g_mapTrie = CreateTrie(); +} + +public OnAllPluginsLoaded() +{ + // This is an MCE cvar... this plugin requires MCE to be loaded. Granted, this plugin SHOULD have an MCE dependency. + g_Cvar_MarkCustomMaps = FindConVar("mce_markcustommaps"); +} + +public OnConfigsExecuted() +{ + if (ReadMapList(g_MapList, + g_mapFileSerial, + "nominations", + MAPLIST_FLAG_CLEARARRAY|MAPLIST_FLAG_MAPSFOLDER) + == INVALID_HANDLE) + { + if (g_mapFileSerial == -1) + { + SetFailState("Unable to create a valid map list."); + } + } + + BuildMapMenu(); +} + +public OnMapTiersLoaded() +{ + BuildMapMenu(); +} + +public OnNominationRemoved(const String:map[], owner) +{ + new status; + + /* Is the map in our list? */ + if (!GetTrieValue(g_mapTrie, map, status)) + { + return; + } + + /* Was the map disabled due to being nominated */ + if ((status & MAPSTATUS_EXCLUDE_NOMINATED) != MAPSTATUS_EXCLUDE_NOMINATED) + { + return; + } + + SetTrieValue(g_mapTrie, map, MAPSTATUS_ENABLED); +} + +public Action:Command_Addmap(client, args) +{ + if (args < 1) + { + CReplyToCommand(client, "[NE] Usage: sm_nominate_addmap "); + return Plugin_Handled; + } + + decl String:mapname[PLATFORM_MAX_PATH]; + GetCmdArg(1, mapname, sizeof(mapname)); + + + new status; + if (!GetTrieValue(g_mapTrie, mapname, status)) + { + CReplyToCommand(client, "%t", "Map was not found", mapname); + return Plugin_Handled; + } + + new NominateResult:result = NominateMap(mapname, true, 0); + + if (result > Nominate_Replaced) + { + /* We assume already in vote is the casue because the maplist does a Map Validity check and we forced, so it can't be full */ + CReplyToCommand(client, "%t", "Map Already In Vote", mapname); + + return Plugin_Handled; + } + + + SetTrieValue(g_mapTrie, mapname, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED); + + + CReplyToCommand(client, "%t", "Map Inserted", mapname); + LogAction(client, -1, "\"%L\" inserted map \"%s\".", client, mapname); + + return Plugin_Handled; +} + +public Action:Command_Say(client, args) +{ + if (!client) + { + return Plugin_Continue; + } + + decl String:text[192]; + if (!GetCmdArgString(text, sizeof(text))) + { + return Plugin_Continue; + } + + new startidx = 0; + if(text[strlen(text)-1] == '"') + { + text[strlen(text)-1] = '\0'; + startidx = 1; + } + + new ReplySource:old = SetCmdReplySource(SM_REPLY_TO_CHAT); + + if (strcmp(text[startidx], "nominate", false) == 0) + { + if (IsNominateAllowed(client)) + { + AttemptNominate(client); + } + } + + SetCmdReplySource(old); + + return Plugin_Continue; +} + +public Action:Command_Nominate(client, args) +{ + if (!client || !IsNominateAllowed(client)) + { + return Plugin_Handled; + } + + if (args == 0) + { + AttemptNominate(client); + return Plugin_Handled; + } + + decl String:mapname[PLATFORM_MAX_PATH]; + GetCmdArg(1, mapname, sizeof(mapname)); + + new status; + if (!GetTrieValue(g_mapTrie, mapname, status)) + { + CReplyToCommand(client, "%t", "Map was not found", mapname); + return Plugin_Handled; + } + + if ((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED) + { + if ((status & MAPSTATUS_EXCLUDE_CURRENT) == MAPSTATUS_EXCLUDE_CURRENT) + { + CReplyToCommand(client, "[NE] %t", "Can't Nominate Current Map"); + } + + if ((status & MAPSTATUS_EXCLUDE_PREVIOUS) == MAPSTATUS_EXCLUDE_PREVIOUS) + { + CReplyToCommand(client, "[NE] %t", "Map in Exclude List"); + } + + if ((status & MAPSTATUS_EXCLUDE_NOMINATED) == MAPSTATUS_EXCLUDE_NOMINATED) + { + CReplyToCommand(client, "[NE] %t", "Map Already Nominated"); + } + + return Plugin_Handled; + } + + new NominateResult:result = NominateMap(mapname, false, client); + + if (result > Nominate_Replaced) + { + if (result == Nominate_AlreadyInVote) + { + CReplyToCommand(client, "%t", "Map Already In Vote", mapname); + } + else + { + CReplyToCommand(client, "[NE] %t", "Map Already Nominated"); + } + + return Plugin_Handled; + } + + /* Map was nominated! - Disable the menu item and update the trie */ + + SetTrieValue(g_mapTrie, mapname, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED); + + decl String:name[MAX_NAME_LENGTH]; + GetClientName(client, name, sizeof(name)); + PrintToChatAll("[NE] %t", "Map Nominated", name, mapname); + LogMessage("%s nominated %s", name, mapname); + + return Plugin_Continue; +} + +AttemptNominate(client) +{ + SetMenuTitle(g_MapMenu, "%T", "Nominate Title", client); + DisplayMenu(g_MapMenu, client, MENU_TIME_FOREVER); + + return; +} + +BuildMapMenu() +{ + if (g_MapMenu != INVALID_HANDLE) + { + CloseHandle(g_MapMenu); + g_MapMenu = INVALID_HANDLE; + } + + ClearTrie(g_mapTrie); + + g_MapMenu = CreateMenu(Handler_MapSelectMenu, MENU_ACTIONS_DEFAULT|MenuAction_DrawItem|MenuAction_DisplayItem); + + decl String:map[PLATFORM_MAX_PATH]; + + new Handle:excludeMaps = INVALID_HANDLE; + decl String:currentMap[32]; + + if (GetConVarBool(g_Cvar_ExcludeOld)) + { + excludeMaps = CreateArray(ByteCountToCells(PLATFORM_MAX_PATH)); + GetExcludeMapList(excludeMaps); + } + + if (GetConVarBool(g_Cvar_ExcludeCurrent)) + { + GetCurrentMap(currentMap, sizeof(currentMap)); + } + + for (new i = 0; i < GetArraySize(g_MapList); i++) + { + new status = MAPSTATUS_ENABLED; + + GetArrayString(g_MapList, i, map, sizeof(map)); + + if (GetConVarBool(g_Cvar_ExcludeCurrent)) + { + if (StrEqual(map, currentMap)) + { + status = MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_CURRENT; + } + } + + /* Dont bother with this check if the current map check passed */ + if (GetConVarBool(g_Cvar_ExcludeOld) && status == MAPSTATUS_ENABLED) + { + if (FindStringInArray(excludeMaps, map) != -1) + { + status = MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_PREVIOUS; + } + } + + decl String:display[32], String:sMap[32]; + strcopy(sMap, sizeof(sMap), map); + ReplaceString(display, sizeof(display), "surf_", "", false); + ReplaceString(display, sizeof(display), "bhop_", "", false); + ReplaceString(display, sizeof(display), "bh_", "", false); + ReplaceString(display, sizeof(display), "mg_", "", false); + Format(display, sizeof(display), "%s [Tier:%d]", map, Timer_GetMapTier(sMap, TRACK_NORMAL)); + AddMenuItem(g_MapMenu, sMap, display); + SetTrieValue(g_mapTrie, sMap, status); + } + + SetMenuExitButton(g_MapMenu, true); + + if (excludeMaps != INVALID_HANDLE) + { + CloseHandle(excludeMaps); + } +} + +public Handler_MapSelectMenu(Handle:menu, MenuAction:action, param1, param2) +{ + switch (action) + { + case MenuAction_Select: + { + decl String:map[PLATFORM_MAX_PATH], String:name[MAX_NAME_LENGTH]; + GetMenuItem(menu, param2, map, sizeof(map)); + + GetClientName(param1, name, MAX_NAME_LENGTH); + + new NominateResult:result = NominateMap(map, false, param1); + + /* Don't need to check for InvalidMap because the menu did that already */ + if (result == Nominate_AlreadyInVote) + { + PrintToChat(param1, "[NE] %t", "Map Already Nominated"); + return 0; + } + else if (result == Nominate_VoteFull) + { + PrintToChat(param1, "[NE] %t", "Max Nominations"); + return 0; + } + + SetTrieValue(g_mapTrie, map, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED); + + if (result == Nominate_Replaced) + { + PrintToChatAll("[NE] %t", "Map Nomination Changed", name, map); + return 0; + } + + PrintToChatAll("[NE] %t", "Map Nominated", name, map); + LogMessage("%s nominated %s", name, map); + } + + case MenuAction_DrawItem: + { + decl String:map[PLATFORM_MAX_PATH]; + GetMenuItem(menu, param2, map, sizeof(map)); + + new status; + + if (!GetTrieValue(g_mapTrie, map, status)) + { + LogError("Menu selection of item not in trie. Major logic problem somewhere."); + return ITEMDRAW_DEFAULT; + } + + if ((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED) + { + return ITEMDRAW_DISABLED; + } + + return ITEMDRAW_DEFAULT; + } + + case MenuAction_DisplayItem: + { + decl String:map[32]; + GetMenuItem(menu, param2, map, sizeof(map)); + + new mark = GetConVarInt(g_Cvar_MarkCustomMaps); + new bool:official; + + new status; + + if (!GetTrieValue(g_mapTrie, map, status)) + { + LogError("Menu selection of item not in trie. Major logic problem somewhere."); + return 0; + } + + decl String:buffer[100]; + decl String:display[150]; + + if (mark) + { + official = IsMapOfficial(map); + } + + if (mark && !official) + { + new tier = Timer_GetMapTier(map, TRACK_NORMAL); + + if(tier > 0) + { + switch (mark) + { + case 1: + { + Format(buffer, sizeof(buffer), "%T [Tier:%d]", "Custom Marked", param1, map, tier); + } + + case 2: + { + Format(buffer, sizeof(buffer), "%T [Tier:%d]", "Custom", param1, map, tier); + } + } + } + else + { + switch (mark) + { + case 1: + { + Format(buffer, sizeof(buffer), "%T", "Custom Marked", param1, map); + } + + case 2: + { + Format(buffer, sizeof(buffer), "%T", "Custom", param1, map); + } + } + } + } + else + { + strcopy(buffer, sizeof(buffer), map); + } + + if ((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED) + { + if ((status & MAPSTATUS_EXCLUDE_CURRENT) == MAPSTATUS_EXCLUDE_CURRENT) + { + Format(display, sizeof(display), "%s (%T)", buffer, "Current Map", param1); + return RedrawMenuItem(display); + } + + if ((status & MAPSTATUS_EXCLUDE_PREVIOUS) == MAPSTATUS_EXCLUDE_PREVIOUS) + { + Format(display, sizeof(display), "%s (%T)", buffer, "Recently Played", param1); + return RedrawMenuItem(display); + } + + if ((status & MAPSTATUS_EXCLUDE_NOMINATED) == MAPSTATUS_EXCLUDE_NOMINATED) + { + Format(display, sizeof(display), "%s (%T)", buffer, "Nominated", param1); + return RedrawMenuItem(display); + } + } + + if (mark && !official) + return RedrawMenuItem(buffer); + + return 0; + } + } + + return 0; +} + +stock bool:IsNominateAllowed(client) +{ + new CanNominateResult:result = CanNominate(); + + switch(result) + { + case CanNominate_No_VoteInProgress: + { + CReplyToCommand(client, "[ME] %t", "Nextmap Voting Started"); + return false; + } + + case CanNominate_No_VoteComplete: + { + new String:map[PLATFORM_MAX_PATH]; + GetNextMap(map, sizeof(map)); + CReplyToCommand(client, "[NE] %t", "Next Map", map); + return false; + } + + case CanNominate_No_VoteFull: + { + CReplyToCommand(client, "[ME] %t", "Max Nominations"); + return false; + } + } + + return true; +} diff --git a/gameserver/addons/sourcemod/scripting/timer-online_db.sp b/gameserver/addons/sourcemod/scripting/timer-online_db.sp index aa49abe..6ca72a6 100644 --- a/gameserver/addons/sourcemod/scripting/timer-online_db.sp +++ b/gameserver/addons/sourcemod/scripting/timer-online_db.sp @@ -10,7 +10,7 @@ new bool:g_bAuthed[MAXPLAYERS + 1]; new Handle:g_hServerID = INVALID_HANDLE; new g_iServerID; -public Plugin:myinfo = +public Plugin:myinfo = { name = "[Timer] Players Online DB", author = "Zipcore", @@ -33,9 +33,9 @@ public OnPluginStart() HookConVarChange(g_hServerID, OnCVarChange); AutoExecConfig(true, "timer/timer-online_DB"); - + RegAdminCmd("sm_online_refresh", Command_RefreshTable, ADMFLAG_ROOT); - + if (g_hSQL == INVALID_HANDLE) { ConnectSQL(); @@ -76,12 +76,16 @@ RefreshTable() decl String:query[512]; Format(query, sizeof(query), "DELETE FROM `online` WHERE `server` = %d", g_iServerID); SQL_TQuery(g_hSQL, DeleteCallback, query, _, DBPrio_High); - + for(new i = 1; i <= MaxClients; i++) { if(IsClientInGame(i) && !IsFakeClient(i) && !IsClientSourceTV(i)) { - g_bAuthed[i] = GetClientAuthString(i, g_sAuth[i], sizeof(g_sAuth[])); + #if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7 + g_bAuthed[i] = GetClientAuthId(i, AuthId_Steam2, g_sAuth[i], sizeof(g_sAuth[])); + #else + g_bAuthed[i] = GetClientAuthString(i, g_sAuth[i], sizeof(g_sAuth[])); + #endif if(g_bAuthed[i]) { FormatEx(query, sizeof(query), "INSERT INTO `online` (auth, server) VALUES ('%s','%d') ON DUPLICATE KEY server = %d;", g_sAuth[i], g_iServerID, g_iServerID); @@ -96,9 +100,13 @@ public OnClientPostAdminCheck(client) g_bAuthed[client] = false; if(IsFakeClient(client) || IsClientSourceTV(client)) return; - - g_bAuthed[client] = GetClientAuthString(client, g_sAuth[client], sizeof(g_sAuth[])); - + + #if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7 + g_bAuthed[client] = GetClientAuthId(client, AuthId_Steam2, g_sAuth[client], sizeof(g_sAuth[])); + #else + g_bAuthed[client] = GetClientAuthString(client, g_sAuth[client], sizeof(g_sAuth[])); + #endif + if (g_hSQL != INVALID_HANDLE) { if(Client_IsValid(client) && !IsFakeClient(client)) @@ -123,10 +131,10 @@ public OnClientDisconnect_Post(client) ConnectSQL() { g_hSQL = Handle:Timer_SqlGetConnection(); - + if (g_hSQL == INVALID_HANDLE) CreateTimer(0.1, Timer_SQLReconnect, _ , TIMER_FLAG_NO_MAPCHANGE); - else + else { SQL_TQuery(g_hSQL, CreateSQLTableCallback, "CREATE TABLE IF NOT EXISTS `online` (`auth` varchar(24) NOT NULL, `server` int(11) NOT NULL, UNIQUE KEY `online_single` (`auth`));"); RefreshTable(); @@ -138,17 +146,17 @@ public CreateSQLTableCallback(Handle:owner, Handle:hndl, const String:error[], a if (owner == INVALID_HANDLE) { Timer_LogError(error); - + ConnectSQL(); return; } - + if (hndl == INVALID_HANDLE) { Timer_LogError("SQL Error on CreateSQLTable: %s", error); return; } - + RefreshTable(); } @@ -174,4 +182,4 @@ public DeleteCallback(Handle:owner, Handle:hndl, const String:error[], any:param Timer_LogError("SQL Error on DeleteCallback: %s", error); return; } -} \ No newline at end of file +} diff --git a/gameserver/addons/sourcemod/scripting/timer-physics.sp b/gameserver/addons/sourcemod/scripting/timer-physics.sp index efcb397..10fee67 100644 --- a/gameserver/addons/sourcemod/scripting/timer-physics.sp +++ b/gameserver/addons/sourcemod/scripting/timer-physics.sp @@ -18,16 +18,11 @@ #include #include -enum UserJumps -{ - Float:LastJumpTimes[4], -} - new bool:g_timerMapzones = false; new bool:g_timerLjStats = false; new bool:g_timerRankings = false; -new g_userJumps[MAXPLAYERS][UserJumps]; +new Float:g_fLastJumps[MAXPLAYERS][4]; new Handle:g_OnClientMaxJumpHeight; new Handle:g_OnClientApplyDifficulty; @@ -159,7 +154,7 @@ public Plugin:myinfo = public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) { RegPluginLibrary("timer-physics"); - + CreateNative("Timer_GetForceStyle", Native_GetForceStyle); CreateNative("Timer_GetPickedStyle", Native_GetPickedStyle); CreateNative("Timer_ApplyPhysics", Native_ApplyPhysics); @@ -168,9 +163,11 @@ public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) CreateNative("Timer_GetMaxSpeed", Native_GetMaxSpeed); CreateNative("Timer_GetAvgSpeed", Native_GetAvgSpeed); CreateNative("Timer_ResetAccuracy", Native_ResetAccuracy); + CreateNative("Timer_SaveLastJumps", Native_SaveLastJumps); + CreateNative("Timer_RestoreLastJumps", Native_RestoreLastJumps); g_bLateLoaded = late; - + return APLRes_Success; } @@ -178,22 +175,22 @@ public OnPluginStart() { LoadPhysics(); LoadTimerSettings(); - + new Handle:hGameConf = INVALID_HANDLE; hGameConf = LoadGameConfigFile("sdkhooks.games"); - if(hGameConf == INVALID_HANDLE) + if(hGameConf == INVALID_HANDLE) { SetFailState("GameConfigFile sdkhooks.games was not found"); return; } - + LoadTranslations("timer.phrases"); - + HookEvent("round_start",Event_RoundStart,EventHookMode_PostNoCopy); - + HookEvent("player_spawn", Event_PlayerSpawn); HookEvent("player_jump", Event_PlayerJump); - + RegAdminCmd("sm_timer_reload_config", Command_ReloadConfig, ADMFLAG_CONVARS, "Reload timer settings"); if(g_Settings[MultimodeEnable]) RegConsoleCmd("sm_style", Command_Difficulty); if(g_Settings[NoclipEnable]) RegConsoleCmd("sm_nc", Command_NoclipMe); @@ -202,24 +199,24 @@ public OnPluginStart() if(g_Settings[BhopEnable]) RegConsoleCmd("sm_autobhop", Command_ToggleAuto); if(g_Settings[BhopEnable]) RegConsoleCmd("sm_autojump", Command_ToggleAuto); RegAdminCmd("sm_colour", Command_Colour, ADMFLAG_RESERVATION); - + g_hPlattformColor = CreateConVar("timer_plattform_color", "0 255 0 255", "The color of detected plattforms."); - + HookConVarChange(g_hPlattformColor, Action_OnSettingsChange); - + AutoExecConfig(true, "timer/timer-physics"); - + new String:buffer[32]; GetConVarString(g_hPlattformColor, buffer, sizeof(buffer)); ParseColor(buffer, g_PlattformColor); - + StartPrepSDKCall(SDKCall_Entity); PrepSDKCall_SetFromConf(hGameConf,SDKConf_Virtual,"Touch"); PrepSDKCall_AddParameter(SDKType_CBaseEntity,SDKPass_Pointer); g_hSDK_Touch = EndPrepSDKCall(); CloseHandle(hGameConf); - if(g_hSDK_Touch == INVALID_HANDLE) + if(g_hSDK_Touch == INVALID_HANDLE) { SetFailState("Unable to prepare virtual function CBaseEntity::Touch"); return; @@ -230,17 +227,17 @@ public OnPluginStart() g_iOffs_vecMins = FindSendPropInfo("CBaseEntity","m_vecMins"); g_iOffs_vecMaxs = FindSendPropInfo("CBaseEntity","m_vecMaxs"); g_iOffs_Velocity = FindSendPropOffs("CBasePlayer", "m_vecVelocity[0]"); - + g_timerMapzones = LibraryExists("timer-mapzones"); g_timerLjStats = LibraryExists("timer-ljstats"); g_timerRankings = LibraryExists("timer-rankings"); - + g_OnClientMaxJumpHeight = CreateGlobalForward("OnClientMaxJumpHeight", ET_Event, Param_Cell, Param_Cell); g_OnClientApplyDifficulty = CreateGlobalForward("OnClientApplyDifficulty", ET_Event, Param_Cell, Param_Cell); g_OnClientApplyDifficultyPre = CreateGlobalForward("OnClientApplyDifficultyPre", ET_Event, Param_Cell, Param_Cell); - - if(g_bLateLoaded) + + if(g_bLateLoaded) { OnPluginPauseChange(false); } @@ -251,31 +248,31 @@ public OnLibraryAdded(const String:name[]) if (StrEqual(name, "timer-mapzones")) { g_timerMapzones = true; - } + } else if (StrEqual(name, "timer-ljstats")) { g_timerLjStats = true; - } + } else if (StrEqual(name, "timer-rankings")) { g_timerRankings = true; - } + } } public OnLibraryRemoved(const String:name[]) -{ +{ if (StrEqual(name, "timer-mapzones")) { g_timerMapzones = false; - } + } else if (StrEqual(name, "timer-ljstats")) { g_timerLjStats = false; - } + } else if (StrEqual(name, "timer-rankings")) { g_timerRankings = false; - } + } } public Action_OnSettingsChange(Handle:cvar, const String:oldvalue[], const String:newvalue[]) @@ -284,9 +281,9 @@ public Action_OnSettingsChange(Handle:cvar, const String:oldvalue[], const Strin ParseColor(newvalue, g_PlattformColor); } -public OnPluginPauseChange(bool:pause) +public OnPluginPauseChange(bool:pause) { - if(pause) + if(pause) { OnPluginEnd(); } @@ -302,7 +299,7 @@ stock ResetMultiBhop() g_iBhopButtonCount = 0; FindBhopBlocks(); - + AlterBhopBlocks(true); g_iBhopDoorCount = 0; @@ -310,12 +307,12 @@ stock ResetMultiBhop() FindBhopBlocks(); } -public Event_RoundStart(Handle:event,const String:name[],bool:dontBroadcast) +public Event_RoundStart(Handle:event,const String:name[],bool:dontBroadcast) { OnPluginPauseChange(false); } -public OnPluginEnd() +public OnPluginEnd() { AlterBhopBlocks(true); @@ -331,7 +328,7 @@ public OnClientPutInServer(client) g_PlattformColorPlayer[client][3] = 255; g_colourme[client] = 0; g_fBoost[client] = 0.0; - + ResetBhopAvoid(client); ResetBhopCollect(client); } @@ -350,7 +347,7 @@ stock ResetStats(client) g_PlattformColorPlayer[client][1] = GetRandomInt(10, 245); g_PlattformColorPlayer[client][2] = GetRandomInt(10, 245); g_PlattformColorPlayer[client][3] = 255; - + g_fSpeedCurrent[client] = 0.0; g_fSpeedMax[client] = 0.0; g_fSpeedTotal[client] = 0.0; @@ -359,14 +356,14 @@ stock ResetStats(client) Teleport(client, bhop, style) { - + decl i; new tele = -1, ent = bhop; //search door trigger list - for (i = 0; i < g_iBhopDoorCount; i++) + for (i = 0; i < g_iBhopDoorCount; i++) { - if(ent == g_iBhopDoorList[i]) + if(ent == g_iBhopDoorList[i]) { tele = g_iBhopDoorTeleList[i]; break; @@ -374,11 +371,11 @@ Teleport(client, bhop, style) } //no destination? search button trigger list - if(tele == -1) + if(tele == -1) { - for (i = 0; i < g_iBhopButtonCount; i++) + for (i = 0; i < g_iBhopButtonCount; i++) { - if(ent == g_iBhopButtonList[i]) + if(ent == g_iBhopButtonList[i]) { tele = g_iBhopButtonTeleList[i]; break; @@ -387,7 +384,7 @@ Teleport(client, bhop, style) } //set teleport destination - if(tele != -1 && IsValidEntity(tele) && g_Physics[style][StyleMultiBhop] != 2) + if(tele != -1 && IsValidEntity(tele) && g_Physics[style][StyleMultiBhop] != 2) { SDKCall(g_hSDK_Touch,tele,client); } @@ -397,12 +394,12 @@ public OnMapStart() { LoadPhysics(); LoadTimerSettings(); - + if(!g_Settings[NoGravityUpdate]) CreateTimer(1.0, Timer_UpdateGravity, _, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT); CreateTimer(0.1, Timer_CheckNoClip, _, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT); - + g_iVegasWinCount = 0; - + ResetMultiBhop(); } @@ -417,34 +414,34 @@ public OnMapEnd() public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) { new client = GetClientOfUserId(GetEventInt(event, "userid")); - + if(0 < client <= MaxClients) { - g_userJumps[client][LastJumpTimes][3] = 0.0; - g_userJumps[client][LastJumpTimes][2] = 0.0; - g_userJumps[client][LastJumpTimes][1] = 0.0; - g_userJumps[client][LastJumpTimes][0] = 0.0; - + g_fLastJumps[client][3] = 0.0; + g_fLastJumps[client][2] = 0.0; + g_fLastJumps[client][1] = 0.0; + g_fLastJumps[client][0] = 0.0; + if(IsFakeClient(client)) return; - + if(GetClientTeam(client) < 2) return; - + g_bPickedStyle[client] = false; - + if(g_StyleDefault == -1) Timer_LogError("PhysicsCFG: No default style found"); - else Timer_SetStyle(client, g_StyleDefault); - + else Timer_SetStyle(client, g_StyleDefault); + ApplyDifficulty(client); - + Timer_SetTrack(client, TRACK_NORMAL); if (g_Settings[StyleMenuOnSpawn]) { FakeClientCommand(client, "sm_style"); } - + if(g_Settings[TeleportOnSpawn]) { FakeClientCommand(client, "sm_restart"); @@ -452,53 +449,101 @@ public Event_PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) } } +new Float:g_fPauseLastJumps[MAXPLAYERS+1][4]; +new Float:g_fPauseStartTime[MAXPLAYERS+1]; + +public OnTimerPaused(client) +{ + StoreAntiBhop(client); +} + +public OnTimerResumed(client) +{ + RestoreAntiBhop(client); +} + +public OnClientStartTouchZoneType(client, MapZoneType:type) +{ + if(!Timer_GetStatus(client) && !Timer_GetPauseStatus(client)) // Timer stopped + if(type == ZtStart || type == ZtBonusStart || type == ZtBonus2Start || type == ZtBonus3Start || type == ZtBonus4Start || type == ZtBonus5Start) + TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, Float:{0.0,0.0,-100.0}); +} + +public Native_SaveLastJumps(Handle:plugin, numParams) +{ + StoreAntiBhop(GetNativeCell(1)); +} + +StoreAntiBhop(client) +{ + g_fPauseStartTime[client] = GetGameTime(); + + g_fPauseLastJumps[client][0] = g_fLastJumps[client][0]; + g_fPauseLastJumps[client][1] = g_fLastJumps[client][1]; + g_fPauseLastJumps[client][2] = g_fLastJumps[client][2]; + g_fPauseLastJumps[client][3] = g_fLastJumps[client][3]; +} + +public Native_RestoreLastJumps(Handle:plugin, numParams) +{ + RestoreAntiBhop(GetNativeCell(1)); +} + +RestoreAntiBhop(client) +{ + g_fLastJumps[client][0] = g_fPauseLastJumps[client][0] + GetGameTime() - g_fPauseStartTime[client]; + g_fLastJumps[client][1] = g_fPauseLastJumps[client][1] + GetGameTime() - g_fPauseStartTime[client]; + g_fLastJumps[client][2] = g_fPauseLastJumps[client][2] + GetGameTime() - g_fPauseStartTime[client]; + g_fLastJumps[client][3] = g_fPauseLastJumps[client][3] + GetGameTime() - g_fPauseStartTime[client]; +} + public Action:Event_PlayerJump(Handle:event, const String:name[], bool:dontBroadcast) { new client = GetClientOfUserId(GetEventInt(event, "userid")); - + new Float:time = GetGameTime(); - + new style = Timer_GetStyle(client); - + g_fLastJump[client] = time; - + GetClientAbsOrigin(client, g_fJumpLastCord[client]); - + if(g_fStamina[client] != -1.0) { SetEntPropFloat(client, Prop_Send, "m_flStamina", g_fStamina[client]); } - + if(g_Physics[style][StyleBoostForward] != 1.0) CreateTimer(0.0, Timer_Boost, client, TIMER_FLAG_NO_MAPCHANGE); - + if(g_Physics[style][StyleMaxSpeed] != 0.0) { CreateTimer(0.05, DelayedSlowDown, client); } - + if(g_Physics[style][StyleAntiBhop] > 0) { - new Float:timediff = time - g_userJumps[client][LastJumpTimes][3]; - g_userJumps[client][LastJumpTimes][3] = g_userJumps[client][LastJumpTimes][2]; - g_userJumps[client][LastJumpTimes][2] = g_userJumps[client][LastJumpTimes][1]; - g_userJumps[client][LastJumpTimes][1] = g_userJumps[client][LastJumpTimes][0]; - g_userJumps[client][LastJumpTimes][0] = time; - - if (timediff <= 4.0 && g_userJumps[client][LastJumpTimes][3] != 0.0 && g_userJumps[client][LastJumpTimes][2] != 0.0) + new Float:timediff = time - g_fLastJumps[client][3]; + g_fLastJumps[client][3] = g_fLastJumps[client][2]; + g_fLastJumps[client][2] = g_fLastJumps[client][1]; + g_fLastJumps[client][1] = g_fLastJumps[client][0]; + g_fLastJumps[client][0] = time; + + if (timediff <= 4.0 && g_fLastJumps[client][3] != 0.0 && g_fLastJumps[client][2] != 0.0) { // If set to 1 prevent bhop everywhere, if set to 2 use it only inside start zones - if(g_Physics[style][StyleAntiBhop] == 1 || Timer_IsPlayerTouchingZoneType(client, ZtStart) || Timer_IsPlayerTouchingZoneType(client, ZtBonusStart)) + if(!Timer_IsPlayerTouchingZoneType(client, ZtBhop) && (g_Physics[style][StyleAntiBhop] == 1 || Timer_IsPlayerTouchingStartZone(client))) { - g_userJumps[client][LastJumpTimes][0] = 0.0; - g_userJumps[client][LastJumpTimes][1] = 0.0; - g_userJumps[client][LastJumpTimes][2] = 0.0; - g_userJumps[client][LastJumpTimes][3] = 0.0; + g_fLastJumps[client][0] = 0.0; + g_fLastJumps[client][1] = 0.0; + g_fLastJumps[client][2] = 0.0; + g_fLastJumps[client][3] = 0.0; CreateTimer(0.05, DelayedSlowDownDefault, client); } } } - + return Plugin_Continue; } @@ -516,37 +561,40 @@ public Action:DelayedSlowDownDefault(Handle:timer, any:client) public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon, &subtype, &cmdnum, &tickcount, &seed, mouse[2]) { new iInitialButtons = buttons; - + if(!IsPlayerAlive(client)) return Plugin_Continue; - + if(Client_IsOnLadder(client)) g_fLastTimeLadderUsed[client] = GetGameTime(); - + new style = Timer_GetStyle(client); new Float:fGameTime = GetGameTime(); new bool:abuse = false; new bool:oldgroundstatus = g_bStayOnGround[client]; new bool:onground = bool:(GetEntityFlags(client) & FL_ONGROUND); + if(onground && !oldgroundstatus) + SetEntityGravity(client, g_Physics[style][StyleGravity]); + new Float:vecVelocity[3]; GetEntDataVector(client, g_iOffs_Velocity, vecVelocity); - + new bool:GainHeight = false; - + if(g_fCord_Old[client][2] < g_fCord_New[client][2]) { GainHeight = true; } - + decl Float:fVelocity[3]; GetEntPropVector(client, Prop_Data, "m_vecVelocity", fVelocity); //velocity new Float:currentspeed = SquareRoot(Pow(fVelocity[0],2.0)+Pow(fVelocity[1],2.0)); //player speed (units per secound) - + g_fSpeedTotal[client] += currentspeed; g_iCommandCount[client] ++; g_fSpeedCurrent[client] = currentspeed; - + if(currentspeed > g_fSpeedMax[client]) { g_fSpeedMax[client] = currentspeed; @@ -555,9 +603,9 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang g_fCord_Old[client][0] = g_fCord_New[client][0]; g_fCord_Old[client][1] = g_fCord_New[client][1]; g_fCord_Old[client][2] = g_fCord_New[client][2]; - + GetClientAbsOrigin(client, g_fCord_New[client]); - + if(g_fCord_Old[client][2] > g_fCord_New[client][2] && GainHeight) { Call_StartForward(g_OnClientMaxJumpHeight); @@ -565,7 +613,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang Call_PushCell(g_fCord_Old[client][2]-g_fJumpLastCord[client][2]); Call_Finish(); } - + if(!onground && !Client_IsOnLadder(client)) { if(!Timer_IsPlayerTouchingZoneType(client, ZtFreeStyle)) @@ -573,15 +621,15 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang if(g_Physics[style][StyleForceHalfSideways] == 1) { g_iMoveCount[client] = 0; - + new Float:fCheck_KeyCounts = 0.25; //time after 2 buttons have to be pressed in seconds new Float:fReset_KeyHits = 3.00; //time after keyhits are resetted in seconds new iCheck_Key_hits = 5; //max keyhits allowed within "fCheck_KeyCounts" time - - + + new Float:fTickrate = 1.0 / GetTickInterval(); //get server tickrate new Float:fCheck_KeyCounts_ticks = fCheck_KeyCounts*fTickrate; //calculate how many ticks has to be ticked to match "fCheck_KeyCounts" time - + if(buttons & IN_FORWARD) { g_iMoveCount[client]++; //count how many keys are pressed @@ -595,7 +643,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang } g_fCount_FORWARD[client] = 0.0; //reset count after key is released } - + if(buttons & IN_BACK) { g_iMoveCount[client]++; //count how many keys are pressed @@ -609,7 +657,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang } g_fCount_BACK[client] = 0.0; //reset count after key is released } - + if(buttons & IN_MOVELEFT) { g_iMoveCount[client]++; //count how many keys are pressed @@ -623,7 +671,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang } g_fCount_MOVELEFT[client] = 0.0; //reset count after key is released } - + if(buttons & IN_MOVERIGHT) { g_iMoveCount[client]++; //count how many keys are pressed @@ -637,11 +685,11 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang } g_fCount_MOVERIGHT[client] = 0.0; //reset count after key is released } - + g_fCount_Keys[client] = g_fCount_FORWARD[client]+g_fCount_BACK[client]+g_fCount_MOVELEFT[client]+g_fCount_MOVERIGHT[client]; //calculate time between button presses - + g_iKey_hits[client] = g_iFORWARD_hits[client]+g_iBACK_hits[client]+g_iMOVELEFT_hits[client]+g_iMOVERIGHT_hits[client]; //calculate all key hits - + if ((g_iMoveCount[client] == 1 && (g_fCount_Keys[client] >= fCheck_KeyCounts_ticks)) || (g_iKey_hits[client] >= iCheck_Key_hits)) //punish the client and reset keyhits/keycounts { abuse = true; @@ -654,7 +702,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang g_iMOVELEFT_hits[client] = 0; g_iMOVERIGHT_hits[client] = 0; } - + if (g_iMoveCount[client] == 2) // reset keyhits/keycounts if 2 buttons are pressed { g_fCount_FORWARD[client] = 0.0; @@ -666,7 +714,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang g_iMOVELEFT_hits[client] = 0; g_iMOVERIGHT_hits[client] = 0; } - + g_iKey_hits_reset[client]++; if(g_iKey_hits_reset[client] > (fReset_KeyHits*fTickrate)) // reset keyhits { @@ -680,23 +728,23 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang else if(g_Physics[style][StyleForceHalfSideways] == 2) { new iMoveCount = 0; - + if(buttons & IN_FORWARD) iMoveCount++; - + if(buttons & IN_BACK) iMoveCount++; - + if(buttons & IN_MOVELEFT) iMoveCount++; - + if(buttons & IN_MOVERIGHT) iMoveCount++; - + if (iMoveCount == 1) abuse = true; } - + if(g_Physics[style][StylePreventMoveleft]) { if (buttons & IN_MOVELEFT || vel[1] < 0) @@ -704,7 +752,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang abuse = true; } } - + if(g_Physics[style][StylePreventMoveright]) { if (buttons & IN_MOVERIGHT || vel[1] > 0) @@ -712,7 +760,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang abuse = true; } } - + if(g_Physics[style][StylePreventPlusleft]) { if (buttons & IN_LEFT) //Can't disable @@ -723,10 +771,10 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang } } } - + if(g_Physics[style][StylePreventPlusright]) { - if (buttons & IN_RIGHT) //Can't disable + if (buttons & IN_RIGHT) //Can't disable { if(Timer_GetStatus(client) > 0) { @@ -734,7 +782,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang } } } - + if(g_Physics[style][StylePreventMoveforward]) { if (buttons & IN_FORWARD || vel[0] > 0) @@ -742,7 +790,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang abuse = true; } } - + if(g_Physics[style][StylePreventMoveback]) { if (buttons & IN_BACK || vel[0] < 0) @@ -750,7 +798,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang abuse = true; } } - + if(g_Physics[style][StyleBlockMovementDirection] != 0) { //backwards @@ -771,7 +819,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang } } } - + if(g_Physics[style][StylePreventPlusleft]) { if(buttons & IN_LEFT) @@ -779,7 +827,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang abuse = true; } } - + if(g_Physics[style][StylePreventPlusright]) { if(buttons & IN_RIGHT) @@ -787,7 +835,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang abuse = true; } } - + if(g_Physics[style][StyleHoverScale] != 0.0) { if(fVelocity[2] < 0.0) @@ -799,19 +847,19 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang } } } - + // Freestyle for players which touched a ladder before if(g_Physics[style][StyleLadderFreestyleCooldown] > 0.0 && GetGameTime() - g_fLastTimeLadderUsed[client] < g_Physics[style][StyleLadderFreestyleCooldown]) { abuse = false; } - + if(abuse) { PunishAbuse(client); g_fUnblockControl[client] = fGameTime+g_Physics[style][StylePunishMovementControlCooldown]; } - else if(g_timerMapzones) + else if(g_timerMapzones) { if(!Timer_IsPlayerTouchingZoneType(client, ZtPushEast) && !Timer_IsPlayerTouchingZoneType(client, ZtPushWest) @@ -826,11 +874,11 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang { Block_MovementControl(client, true); } - + if (buttons & IN_JUMP) { new bool:boost = false; - + if(g_timerMapzones) { if(!Timer_IsPlayerTouchingZoneType(client, ZtNoBoost)) @@ -839,17 +887,17 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang } } else boost = true; - + if(boost && onground && g_fBoost[client] > 0.0) { g_bPushWait[client] = true; CreateTimer(0.0, Timer_Push, client, TIMER_FLAG_NO_MAPCHANGE); } - + if(!onground) { new auto = false; - + if(g_timerMapzones) { //Settings/Zone check @@ -859,7 +907,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang } } else auto = true; - + if(auto) { //Ladder check @@ -883,7 +931,7 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang new oldjumps = g_iFullJumpCount[client]; new bool:perfect = false; - + // Ignore this jump if the player is in a tight space or stuck in the ground. if ((buttons & IN_JUMP) && !abuse) { @@ -899,41 +947,36 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang g_iFullJumpCount[client]++; g_fJumpAccuracy[client] = 100-((100/g_Settings[MultiBhopDelay])*g_fFullJumpTimeAmount[client])/g_iFullJumpCount[client]; } - else - { - fCheckTime[client] = fGameTime + g_Settings[MultiBhopJumpTime]; - } + else fCheckTime[client] = fGameTime + g_Settings[MultiBhopJumpTime]; } else if(fCheckTime[client] != 0.0) - { fCheckTime[client] = 0.0; - } } } - + if(!abuse && !perfect) { //Save new on ground status - if(onground) + if(onground) { - if(!g_bStayOnGround[client] && g_fBoost[client] > 0.0) + if(!g_bStayOnGround[client] && g_fBoost[client] > 0.0) { g_bPushWait[client] = false; } - + g_bStayOnGround[client] = true; } else { g_bStayOnGround[client] = false; } - + //Player landed if(g_bStayOnGround[client] && g_bStayOnGround[client] != oldgroundstatus) { g_fLandedTime[client] = fGameTime; } - + //Player jumped if(!g_bStayOnGround[client] && g_bStayOnGround[client] != oldgroundstatus) { @@ -942,11 +985,11 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang g_iFullJumpCount[client]++; } } - + //Player has jumped? How good was his jump? if(oldjumps < g_iFullJumpCount[client]) //don't count first jump { - if(fGameTime-g_fLandedTime[client] > g_Settings[MultiBhopDelay]) + if(fGameTime-g_fLandedTime[client] > g_Settings[MultiBhopDelay]) { g_fFullJumpTimeAmount[client] += g_Settings[MultiBhopDelay]; } @@ -954,17 +997,17 @@ public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:ang { g_fFullJumpTimeAmount[client] += fGameTime-g_fLandedTime[client]; } - + //update jump accuracy g_fJumpAccuracy[client] = 100-((100/g_Settings[MultiBhopDelay])*g_fFullJumpTimeAmount[client])/g_iFullJumpCount[client]; } } - + iPrevButtons[client] = buttons; - + if(iInitialButtons != buttons) return Plugin_Changed; - + return Plugin_Continue; } @@ -984,31 +1027,31 @@ CreatePhysicsMenu(client, MCategory:category) if(category == MCategory_Ranked) SetMenuTitle(menu, "Ranked Styles", client); else if(category == MCategory_Fun) SetMenuTitle(menu, "Fun Styles", client); else if(category == MCategory_Practise) SetMenuTitle(menu, "Practise Styles", client); - + SetMenuExitBackButton(menu, true); SetMenuExitButton(menu, true); - + new count = 0; new found = 0; - + new maxorder[3] = {0, ...}; - for (new i = 0; i < MAX_STYLES-1; i++) + for (new i = 0; i < MAX_STYLES-1; i++) { if(!g_Physics[i][StyleEnable]) continue; if(g_Physics[i][StyleCategory] != category) continue; - + if(g_Physics[i][StyleOrder] > maxorder[category]) maxorder[category] = g_Physics[i][StyleOrder]; - + count++; } - - for (new order = 0; order <= maxorder[category]; order++) + + for (new order = 0; order <= maxorder[category]; order++) { - for (new i = 0; i < MAX_STYLES-1; i++) + for (new i = 0; i < MAX_STYLES-1; i++) { if(!g_Physics[i][StyleEnable]) continue; @@ -1016,15 +1059,15 @@ CreatePhysicsMenu(client, MCategory:category) continue; if(g_Physics[i][StyleOrder] != order) continue; - + found++; - + new String:buffer[8]; IntToString(i, buffer, sizeof(buffer)); - + AddMenuItem(menu, buffer, g_Physics[i][StyleName]); } - + if(found == count) break; } @@ -1035,17 +1078,16 @@ CreatePhysicsMenu(client, MCategory:category) public MenuHandler_Physics(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Cancel) + else if (action == MenuAction_Cancel) { - if (itemNum == MenuCancel_ExitBack) - { - if(IsClientInGame(client)) FakeClientCommand(client, "sm_style"); - } - } + if (itemNum == MenuCancel_ExitBack) + if(IsClientInGame(client)) + FakeClientCommand(client, "sm_style"); + } else if ( action == MenuAction_Select ) { decl String:info[100], String:info2[100]; @@ -1053,29 +1095,26 @@ public MenuHandler_Physics(Handle:menu, MenuAction:action, client, itemNum) if(found) { new style = StringToInt(info); - + if(0 <= style < MAX_STYLES-1 && g_Physics[style][StyleEnable]) { if((g_iBhopButtonCount == 0 && g_iBhopDoorCount == 0) && g_Physics[style][StyleMultiBhop] > 0) { CPrintToChat(client, PLUGIN_PREFIX, "Multi bhop not available", client); - if(IsClientInGame(client)) FakeClientCommand(client, "sm_style"); + if(IsClientInGame(client)) + FakeClientCommand(client, "sm_style"); } else { g_bPickedStyle[client] = true; Timer_SetStyle(client, style); - + if(g_Physics[style][StyleCustom]) - { CreateCustomMenu(client); - } } } - else - { - if(IsClientInGame(client)) FakeClientCommand(client, "sm_style"); - } + else if(IsClientInGame(client)) + FakeClientCommand(client, "sm_style"); } } } @@ -1097,7 +1136,7 @@ CreateDifficultyMenu(client) SetMenuTitle(menu, "Styles", client); SetMenuExitButton(menu, true); - + if(g_StyleCountRankedEnabled > 0) { AddMenuItem(menu, "timed", "Ranked Styles"); @@ -1110,9 +1149,9 @@ CreateDifficultyMenu(client) { AddMenuItem(menu, "practise", "Practise Styles"); } - + AddMenuItem(menu, "main", "Back"); - + DisplayMenu(menu, client, MENU_TIME_FOREVER); } } @@ -1122,7 +1161,7 @@ CreateDifficultyMenu(client) public MenuHandler_Difficulty(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } @@ -1154,11 +1193,13 @@ public MenuHandler_Difficulty(Handle:menu, MenuAction:action, client, itemNum) } else if(StrEqual(info, "main")) { - if(IsClientInGame(client)) FakeClientCommand(client, "sm_menu"); + if(IsClientInGame(client)) + FakeClientCommand(client, "sm_menu"); } else { - if(IsClientInGame(client)) FakeClientCommand(client, "sm_style"); + if(IsClientInGame(client)) + FakeClientCommand(client, "sm_style"); } } } @@ -1191,17 +1232,13 @@ public MenuHandler_Settings(Handle:menu, MenuAction:action, client, itemNum) { if(0 < client < MaxClients) { - if (action == MenuAction_End) + if (action == MenuAction_End) { if(IsClientConnected(client)) FakeClientCommand(client, "sm_style"); } else if ( action == MenuAction_Select ) { - if(GetClientTeam(client) < 2) - { - - } - else + if(GetClientTeam(client) >= 2) { decl String:info[100], String:info2[100]; new bool:found = GetMenuItem(menu, itemNum, info, sizeof(info), _, info2, sizeof(info2)); @@ -1239,9 +1276,9 @@ public MenuHandler_Settings(Handle:menu, MenuAction:action, client, itemNum) { g_bCustomLowGravity[client] = false; } - + CreateSettingsMenu(client); - + ApplyDifficulty(client); } } @@ -1262,13 +1299,13 @@ CreateCustomMenu(client) if(!g_bCustomAuto[client]) AddMenuItem(menu, "enable_auto", "Enable Auto-Mode"); else AddMenuItem(menu, "disable_auto", "Disable Auto-Mode"); - + if(!g_bCustomBoost[client]) AddMenuItem(menu, "enable_boost", "Enable Jump Height Boost"); else AddMenuItem(menu, "disable_boost", "Disable Jump Height Boost"); - + if(!g_bCustomFullStamina[client]) AddMenuItem(menu, "enable_stamina", "Enable Speed Loss (Stamina)"); else AddMenuItem(menu, "disable_stamina", "Disable Speed Loss (Stamina)"); - + if(!g_bCustomLowGravity[client]) AddMenuItem(menu, "enable_lowgravity", "Enable Low Gravity"); else AddMenuItem(menu, "disable_lowgravity", "Disable Low Gravity"); @@ -1279,7 +1316,7 @@ public MenuHandler_Custom(Handle:menu, MenuAction:action, client, itemNum) { if(0 < client < MaxClients) { - if (action == MenuAction_End) + if (action == MenuAction_End) { if(IsClientConnected(client)) FakeClientCommand(client, "sm_bhop"); } @@ -1287,7 +1324,7 @@ public MenuHandler_Custom(Handle:menu, MenuAction:action, client, itemNum) { if(GetClientTeam(client) < 2) { - + } else { @@ -1327,9 +1364,9 @@ public MenuHandler_Custom(Handle:menu, MenuAction:action, client, itemNum) { g_bCustomLowGravity[client] = false; } - + CreateCustomMenu(client); - + ApplyDifficulty(client); } } @@ -1346,23 +1383,23 @@ ApplyDifficulty(client) if (IsClientInGame(client) && IsClientConnected(client) && !IsClientSourceTV(client)) { new style = Timer_GetStyle(client); - + Call_StartForward(g_OnClientApplyDifficultyPre); Call_PushCell(client); Call_PushCell(style); Call_Finish(); - + // Get style again for the case it was changed on the forward style = Timer_GetStyle(client); - + if(g_Physics[style][StyleCustom]) { if(g_bCustomFullStamina[client]) g_fStamina[client] = STAMINA_FULL; else g_fStamina[client] = STAMINA_DISABLED; - + if(g_bCustomBoost[client]) g_fBoost[client] = g_Physics[style][StyleBoost]; else g_fBoost[client] = 0.0; - + g_bAuto[client] = g_bCustomAuto[client]; } else @@ -1371,49 +1408,43 @@ ApplyDifficulty(client) g_bAuto[client] = g_Physics[style][StyleAuto]; g_fBoost[client] = g_Physics[style][StyleBoost]; } - + //only allow on normal if(!g_Physics[style][StyleLJStats] && g_timerLjStats) { SetLJMode(client, false); } - + //stop timer Timer_Stop(client); - + SetEntityGravity(client, g_Physics[style][StyleGravity]); - + //stop him TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, Float:{0.0,0.0,-100.0}); - + SetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue", g_Physics[style][StyleTimeScale]); - + SetEntProp(client, Prop_Send, "m_iFOV", g_Physics[style][StyleFOV]); SetEntProp(client, Prop_Send, "m_iDefaultFOV", g_Physics[style][StyleFOV]); - + decl String:auth[32]; #if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7 GetClientAuthId(client, AuthId_Steam2, auth, sizeof(auth)); #else GetClientAuthString(client, auth, sizeof(auth)); #endif - - if(StrEqual(g_Physics[style][StyleDesc], "")) - { - - } - else - { + + if(!StrEqual(g_Physics[style][StyleDesc], "")) CPrintToChat(client, "%s %s", PLUGIN_PREFIX2, g_Physics[style][StyleDesc]); - } - + if(g_Settings[TeleportOnStyleChanged]) { if(Timer_GetTrack(client) == TRACK_BONUS) FakeClientCommand(client, "sm_b"); else FakeClientCommand(client, "sm_start"); } - + Call_StartForward(g_OnClientApplyDifficulty); Call_PushCell(client); Call_PushCell(style); @@ -1444,10 +1475,10 @@ public Native_GetMaxSpeed(Handle:plugin, numParams) public Native_GetAvgSpeed(Handle:plugin, numParams) { new client = GetNativeCell(1); - + if(g_iCommandCount[client] <= 0) return false; - + SetNativeCellRef(2, g_fSpeedTotal[client]/g_iCommandCount[client]); return true; } @@ -1469,43 +1500,27 @@ public Native_ResetAccuracy(Handle:plugin, numParams) g_iFullJumpCount[client] = 0; } -stock SetThirdPersonView(client, bool:third) -{ - if(third) - { - SetEntPropEnt(client, Prop_Send, "m_hObserverTarget", 0); - SetEntProp(client, Prop_Send, "m_iObserverMode", 1); - SetEntProp(client, Prop_Send, "m_bDrawViewmodel", 0); - } - else if(!third) - { - SetEntPropEnt(client, Prop_Send, "m_hObserverTarget", -1); - SetEntProp(client, Prop_Send, "m_iObserverMode", 0); - SetEntProp(client, Prop_Send, "m_bDrawViewmodel", 1); - } -} - -public Entity_Touch(bhop,client) +public Entity_Touch(bhop,client) { new doorID = GetBhopDoorID(bhop); new buttonID = GetBhopButtonID(bhop); - + //bhop = entity - if(0 < client <= MaxClients) + if(0 < client <= MaxClients) { new style = Timer_GetStyle(client); - + if(g_Settings[VegasEnable]) { new bool:avoid; - + if(doorID != -1 && g_bBhopDoorAvoid[doorID]) { if(!g_bBhopDoorClientAvoid[doorID][client]) { g_bBhopDoorClientAvoid[doorID][client] = true; avoid = true; - if(g_iBhopClientAvoid[client] == 1) + if(g_iBhopClientAvoid[client] == 1) CPrintToChat(client, PLUGIN_PREFIX, "You failed vegas mission", client); } } @@ -1515,20 +1530,20 @@ public Entity_Touch(bhop,client) { g_bBhopButtonClientAvoid[buttonID][client] = true; avoid = true; - if(g_iBhopClientAvoid[client] == 1) + if(g_iBhopClientAvoid[client] == 1) CPrintToChat(client, PLUGIN_PREFIX, "You failed vegas mission", client); } } - + if(avoid) { g_iBhopClientAvoid[client]++; - + ResetBhopCollect(client); } - + new bool:collect; - + if(doorID != -1 && g_bBhopDoorCollect[doorID]) { if(!g_bBhopDoorClientCollect[doorID][client]) @@ -1545,27 +1560,27 @@ public Entity_Touch(bhop,client) collect = true; } } - + if(collect) { g_iBhopClientCollect[client]++; - + if(GetBhopCollectComplete(client)) { g_iVegasWinCount++; - + if(g_timerRankings) { Timer_AddPoints(client, g_Settings[PointsVegas]+(g_Settings[PointsVegasAdd]*g_iVegasWinCount)); Timer_SavePoints(client); - + decl String:sName[32]; GetClientName(client, sName, sizeof(sName)); CPrintToChatAll(PLUGIN_PREFIX, "Vegas won", sName, g_Settings[PointsVegasAdd]*g_iVegasWinCount); AlterBhopBlocks(true); AlterBhopBlocks(false); } - + if(g_iVegasWinCount >= g_Settings[VegasMapMaxGames]) { CPrintToChatAll(PLUGIN_PREFIX, "Vegas final game"); @@ -1577,27 +1592,27 @@ public Entity_Touch(bhop,client) } } } - + static Float:flPunishTime[MAXPLAYERS + 1], iLastBlock[MAXPLAYERS + 1] = { -1,... }; - + new Float:time = GetGameTime(); - + new Float:diff = time - flPunishTime[client]; - + if ((GetUserFlagBits(client) & ADMFLAG_RESERVATION) && g_colourme[client]) { SetEntDataArray(bhop, g_iOffs_clrRender , g_PlattformColorPlayer[client], 4, 1, true); CreateTimer(0.5, RemoveColouredBlocks,bhop); } - - if(iLastBlock[client] != bhop || diff > g_Settings[MultiBhopCooldown]) + + if(iLastBlock[client] != bhop || diff > g_Settings[MultiBhopCooldown]) { //reset cooldown iLastBlock[client] = bhop; flPunishTime[client] = time + g_Settings[MultiBhopDelay]; - + } - else if(diff > g_Settings[MultiBhopDelay]) + else if(diff > g_Settings[MultiBhopDelay]) { if(g_Physics[style][StyleMultiBhop] == 1 && time - g_fLastJump[client] > (g_Settings[MultiBhopCooldown] + g_Settings[MultiBhopDelay])) { @@ -1619,16 +1634,16 @@ public Action:RemoveColouredBlocks(Handle:timer, any:bhop) SetEntDataArray(bhop, g_iOffs_clrRender , colour, 4, 1, true); } -FindBhopBlocks() +FindBhopBlocks() { if(g_Settings[MultiBhopEnable]) { decl Float:startpos[3], Float:endpos[3], Float:mins[3], Float:maxs[3], tele; new ent = -1; - while((ent = FindEntityByClassname(ent,"func_door")) != -1) + while((ent = FindEntityByClassname(ent,"func_door")) != -1) { - if(g_iDoorOffs_vecPosition1 == -1) + if(g_iDoorOffs_vecPosition1 == -1) { g_iDoorOffs_vecPosition1 = FindDataMapOffs(ent,"m_vecPosition1"); g_iDoorOffs_vecPosition2 = FindDataMapOffs(ent,"m_vecPosition2"); @@ -1642,7 +1657,7 @@ FindBhopBlocks() GetEntDataVector(ent,g_iDoorOffs_vecPosition1,startpos); GetEntDataVector(ent,g_iDoorOffs_vecPosition2,endpos); - if(startpos[2] > endpos[2]) + if(startpos[2] > endpos[2]) { GetEntDataVector(ent,g_iOffs_vecMins,mins); GetEntDataVector(ent,g_iOffs_vecMaxs,maxs); @@ -1651,12 +1666,12 @@ FindBhopBlocks() startpos[1] += (mins[1] + maxs[1]) * 0.5; startpos[2] += maxs[2]; - if((tele = CustomTraceForTeleports(startpos,endpos[2] + maxs[2])) != -1) + if((tele = CustomTraceForTeleports(startpos,endpos[2] + maxs[2])) != -1) { g_iBhopDoorList[g_iBhopDoorCount] = ent; g_iBhopDoorTeleList[g_iBhopDoorCount] = tele; - if(++g_iBhopDoorCount == sizeof g_iBhopDoorList) + if(++g_iBhopDoorCount == sizeof g_iBhopDoorList) { break; } @@ -1666,9 +1681,9 @@ FindBhopBlocks() ent = -1; - while((ent = FindEntityByClassname(ent,"func_button")) != -1) + while((ent = FindEntityByClassname(ent,"func_button")) != -1) { - if(g_iButtonOffs_vecPosition1 == -1) + if(g_iButtonOffs_vecPosition1 == -1) { g_iButtonOffs_vecPosition1 = FindDataMapOffs(ent,"m_vecPosition1"); g_iButtonOffs_vecPosition2 = FindDataMapOffs(ent,"m_vecPosition2"); @@ -1679,7 +1694,7 @@ FindBhopBlocks() GetEntDataVector(ent,g_iButtonOffs_vecPosition1,startpos); GetEntDataVector(ent,g_iButtonOffs_vecPosition2,endpos); - if(startpos[2] > endpos[2] && (GetEntData(ent,g_iButtonOffs_spawnflags,4) & SF_BUTTON_TOUCH_ACTIVATES)) + if(startpos[2] > endpos[2] && (GetEntData(ent,g_iButtonOffs_spawnflags,4) & SF_BUTTON_TOUCH_ACTIVATES)) { GetEntDataVector(ent,g_iOffs_vecMins,mins); GetEntDataVector(ent,g_iOffs_vecMaxs,maxs); @@ -1688,12 +1703,12 @@ FindBhopBlocks() startpos[1] += (mins[1] + maxs[1]) * 0.5; startpos[2] += maxs[2]; - if((tele = CustomTraceForTeleports(startpos,endpos[2] + maxs[2])) != -1) + if((tele = CustomTraceForTeleports(startpos,endpos[2] + maxs[2])) != -1) { g_iBhopButtonList[g_iBhopButtonCount] = ent; g_iBhopButtonTeleList[g_iBhopButtonCount] = tele; - if(++g_iBhopButtonCount == sizeof g_iBhopButtonList) + if(++g_iBhopButtonCount == sizeof g_iBhopButtonList) { break; } @@ -1706,77 +1721,77 @@ FindBhopBlocks() stock GetBhopDoorID(entity) { - for (new i = 0; i < g_iBhopDoorCount; i++) + for (new i = 0; i < g_iBhopDoorCount; i++) { if(entity == g_iBhopDoorList[i]) return i; } - + return -1; } stock GetBhopButtonID(entity) { - for (new i = 0; i < g_iBhopButtonCount; i++) + for (new i = 0; i < g_iBhopButtonCount; i++) { if(entity == g_iBhopButtonList[i]) return i; } - + return -1; } stock bool:GetBhopAvoidComplete(client) { - for (new i = 0; i < g_iBhopDoorCount; i++) + for (new i = 0; i < g_iBhopDoorCount; i++) { if(!g_bBhopDoorAvoid[i]) continue; - + if(g_bBhopDoorClientAvoid[i][client]) return false; } - - for (new i = 0; i < g_iBhopButtonCount; i++) + + for (new i = 0; i < g_iBhopButtonCount; i++) { if(!g_bBhopButtonAvoid[i]) continue; - + if(g_bBhopButtonClientAvoid[i][client]) return false; } - + return true; } stock bool:GetBhopCollectComplete(client) { - for (new i = 0; i < g_iBhopDoorCount; i++) + for (new i = 0; i < g_iBhopDoorCount; i++) { if(!g_bBhopDoorCollect[i]) continue; - + if(!g_bBhopDoorClientCollect[i][client]) return false; } - - for (new i = 0; i < g_iBhopButtonCount; i++) + + for (new i = 0; i < g_iBhopButtonCount; i++) { if(!g_bBhopButtonCollect[i]) continue; - + if(!g_bBhopButtonClientCollect[i][client]) return false; } - + return true; } stock ResetBhopAvoid(client) { g_iBhopClientAvoid[client] = 0; - - for (new i = 0; i < g_iBhopDoorCount; i++) + + for (new i = 0; i < g_iBhopDoorCount; i++) { g_bBhopDoorClientAvoid[i][client] = false; g_bBhopButtonClientAvoid[i][client] = false; @@ -1786,15 +1801,15 @@ stock ResetBhopAvoid(client) stock ResetBhopCollect(client) { g_iBhopClientCollect[client] = 0; - - for (new i = 0; i < g_iBhopDoorCount; i++) + + for (new i = 0; i < g_iBhopDoorCount; i++) { g_bBhopDoorClientCollect[i][client] = false; g_bBhopButtonClientCollect[i][client] = false; } } -AlterBhopBlocks(bool:bRevertChanges) +AlterBhopBlocks(bool:bRevertChanges) { if(g_Settings[MultiBhopEnable]) { @@ -1809,12 +1824,12 @@ AlterBhopBlocks(bool:bRevertChanges) decl ent, i; - if(bRevertChanges) + if(bRevertChanges) { g_iBhopCollectMax = 0; g_iBhopAvoidMax = 0; - - for (i = 0; i < g_iBhopDoorCount; i++) + + for (i = 0; i < g_iBhopDoorCount; i++) { ent = g_iBhopDoorList[i]; g_bBhopDoorAvoid[i] = false; @@ -1825,15 +1840,15 @@ AlterBhopBlocks(bool:bRevertChanges) g_bBhopDoorClientAvoid[i][client] = false; g_bBhopDoorClientCollect[i][client] = false; } - - if(IsValidEntity(ent)) + + if(IsValidEntity(ent)) { SetEntDataArray(ent, g_iOffs_clrRender , {255, 255, 255, 255}, 4, 1, true); SetEntDataVector(ent,g_iDoorOffs_vecPosition2,vecDoorPosition2[i]); SetEntDataFloat(ent,g_iDoorOffs_flSpeed,flDoorSpeed[i]); SetEntData(ent,g_iDoorOffs_spawnflags,iDoorSpawnflags[i],4); - - if(!bDoorLocked[i]) + + if(!bDoorLocked[i]) { AcceptEntityInput(ent,"Unlock"); } @@ -1842,10 +1857,10 @@ AlterBhopBlocks(bool:bRevertChanges) } } - for (i = 0; i < g_iBhopButtonCount; i++) + for (i = 0; i < g_iBhopButtonCount; i++) { ent = g_iBhopButtonList[i]; - + g_bBhopButtonAvoid[i] = false; g_bBhopButtonCollect[i] = false; @@ -1854,8 +1869,8 @@ AlterBhopBlocks(bool:bRevertChanges) g_bBhopButtonClientAvoid[i][client] = false; g_bBhopButtonClientCollect[i][client] = false; } - - if(IsValidEntity(ent)) + + if(IsValidEntity(ent)) { SetEntDataArray(ent, g_iOffs_clrRender , {255, 255, 255, 255}, 4, 1, true); SetEntDataVector(ent,g_iButtonOffs_vecPosition2,vecButtonPosition2[i]); @@ -1866,30 +1881,30 @@ AlterBhopBlocks(bool:bRevertChanges) } } } - else + else { g_iBhopCollectMax = 0; g_iBhopAvoidMax = 0; - + g_PlattformColorAvoid[0] = 255; g_PlattformColorAvoid[1] = 0; g_PlattformColorAvoid[2] = 0; g_PlattformColorAvoid[3] = 255; - + g_PlattformColorCollect[0] = 0; g_PlattformColorCollect[1] = 255; g_PlattformColorCollect[2] = 0; g_PlattformColorCollect[3] = 255; - + new Float:random; - + //note: This only gets called directly after finding the blocks, so the entities are valid. decl Float:startpos[3]; - for (i = 0; i < g_iBhopDoorCount; i++) + for (i = 0; i < g_iBhopDoorCount; i++) { ent = g_iBhopDoorList[i]; - + if(g_Settings[VegasEnable] && g_Settings[VegasMinPlattfors] <= g_iBhopDoorCount+g_iBhopButtonCount && (g_iVegasWinCount < g_Settings[VegasMapMaxGames] || g_Settings[VegasMapMaxGames] == 0)) { for (new client = 1; client <= MaxClients; client++) @@ -1901,23 +1916,23 @@ AlterBhopBlocks(bool:bRevertChanges) } random = GetRandomFloat(0.0, 100.0); - + new Float:avoidchance = g_Settings[VegasAvoidChance]+(g_Settings[VegasAvoidChanceAdd]*g_iVegasWinCount); - - if(random < avoidchance) + + if(random < avoidchance) { g_bBhopDoorAvoid[i] = true; g_iBhopAvoidMax++; SetEntDataArray(ent, g_iOffs_clrRender , g_PlattformColorAvoid, 4, 1, true); } - else if(random < avoidchance+g_Settings[VegasCollectChance]+(g_Settings[VegasCollectChanceAdd]*g_iVegasWinCount)) + else if(random < avoidchance+g_Settings[VegasCollectChance]+(g_Settings[VegasCollectChanceAdd]*g_iVegasWinCount)) { g_bBhopDoorCollect[i] = true; g_iBhopCollectMax++; SetEntDataArray(ent, g_iOffs_clrRender , g_PlattformColorCollect, 4, 1, true); } } - + GetEntDataVector(ent,g_iDoorOffs_vecPosition2,vecDoorPosition2[i]); flDoorSpeed[i] = GetEntDataFloat(ent,g_iDoorOffs_flSpeed); iDoorSpawnflags[i] = GetEntData(ent,g_iDoorOffs_spawnflags,4); @@ -1935,7 +1950,7 @@ AlterBhopBlocks(bool:bRevertChanges) SDKHook(ent,SDKHook_Touch,Entity_Touch); } - for (i = 0; i < g_iBhopButtonCount; i++) + for (i = 0; i < g_iBhopButtonCount; i++) { ent = g_iBhopButtonList[i]; @@ -1950,14 +1965,14 @@ AlterBhopBlocks(bool:bRevertChanges) } random = GetRandomFloat(0.0, 100.0); - - if(random < g_Settings[VegasAvoidChance]) + + if(random < g_Settings[VegasAvoidChance]) { SetEntDataArray(ent, g_iOffs_clrRender , g_PlattformColorAvoid, 4, 1, true); g_iBhopAvoidMax++; g_bBhopButtonAvoid[i] = true; } - else if(random < g_Settings[VegasCollectChance]+g_Settings[VegasAvoidChance]) + else if(random < g_Settings[VegasCollectChance]+g_Settings[VegasAvoidChance]) { SetEntDataArray(ent, g_iOffs_clrRender , g_PlattformColorCollect, 4, 1, true); g_iBhopCollectMax++; @@ -1981,12 +1996,12 @@ AlterBhopBlocks(bool:bRevertChanges) } } -CustomTraceForTeleports(const Float:startpos[3],Float:endheight,Float:step=1.0) +CustomTraceForTeleports(const Float:startpos[3],Float:endheight,Float:step=1.0) { decl teleports[512]; new tpcount, ent = -1; - while((ent = FindEntityByClassname(ent,"trigger_teleport")) != -1 && tpcount != sizeof teleports) + while((ent = FindEntityByClassname(ent,"trigger_teleport")) != -1 && tpcount != sizeof teleports) { teleports[tpcount++] = ent; } @@ -1997,13 +2012,14 @@ CustomTraceForTeleports(const Float:startpos[3],Float:endheight,Float:step=1.0) origin[1] = startpos[1]; origin[2] = startpos[2]; - do { - for (i = 0; i < tpcount; i++) + do + { + for (i = 0; i < tpcount; i++) { ent = teleports[i]; GetAbsBoundingBox(ent,mins,maxs); - if(mins[0] <= origin[0] <= maxs[0] && mins[1] <= origin[1] <= maxs[1] && mins[2] <= origin[2] <= maxs[2]) + if(mins[0] <= origin[0] <= maxs[0] && mins[1] <= origin[1] <= maxs[1] && mins[2] <= origin[2] <= maxs[2]) { return ent; } @@ -2015,7 +2031,7 @@ CustomTraceForTeleports(const Float:startpos[3],Float:endheight,Float:step=1.0) return -1; } -GetAbsBoundingBox(ent,Float:mins[3],Float:maxs[3]) +GetAbsBoundingBox(ent,Float:mins[3],Float:maxs[3]) { decl Float:origin[3]; @@ -2040,11 +2056,11 @@ public Action:Timer_UpdateGravity(Handle:timer) { if(IsClientConnected(client) && IsClientSourceTV(client)) continue; - + if(g_timerMapzones) - if(Timer_IsPlayerTouchingZoneType(client, ZtNoGravityOverwrite)) + if(Timer_IsPlayerTouchingZoneType(client, ZtNoGravityOverwrite)) continue; - + //gravity update new style = Timer_GetStyle(client); if(g_Physics[style][StyleCustom] && !g_bCustomLowGravity[client]) @@ -2057,7 +2073,7 @@ public Action:Timer_UpdateGravity(Handle:timer) SetEntityGravity(client, g_Physics[style][StyleGravity]); continue; } - + SetEntityGravity(client, 1.0); } } @@ -2073,7 +2089,7 @@ public Action:Timer_CheckNoClip(Handle:timer) { if(IsClientConnected(client) && IsClientSourceTV(client)) continue; - + //has player noclip? if(GetEntProp(client, Prop_Send, "movetype", 1) == 8) { @@ -2082,7 +2098,7 @@ public Action:Timer_CheckNoClip(Handle:timer) SetEntityMoveType(client, MOVETYPE_WALK); CheckVelocity(client, 1, 0.1); } - + Timer_Stop(client, false); ResetBhopAvoid(client); ResetBhopCollect(client); @@ -2097,7 +2113,7 @@ ParseColor(const String:color[], result[]) { decl String:buffers[4][4]; ExplodeString(color, " ", buffers, sizeof(buffers), sizeof(buffers[])); - + for (new i = 0; i < sizeof(buffers); i++) result[i] = StringToInt(buffers[i]); } @@ -2106,33 +2122,33 @@ stock Client_Push(client, Float:clientEyeAngle[3], Float:power, VelocityOverride { decl Float:forwardVector[3], Float:newVel[3]; - + GetAngleVectors(clientEyeAngle, forwardVector, NULL_VECTOR, NULL_VECTOR); NormalizeVector(forwardVector, forwardVector); ScaleVector(forwardVector, power); - + Entity_GetAbsVelocity(client,newVel); - + for (new i=0;i<3;i++){ switch(override[i]){ case VelocityOvr_Velocity:{ newVel[i] = 0.0; } - case VelocityOvr_OnlyWhenNegative:{ + case VelocityOvr_OnlyWhenNegative:{ if(newVel[i] < 0.0){ newVel[i] = 0.0; } } - case VelocityOvr_InvertReuseVelocity:{ + case VelocityOvr_InvertReuseVelocity:{ if(newVel[i] < 0.0){ newVel[i] *= -1.0; } } } - + newVel[i] += forwardVector[i]; } - + Entity_SetAbsVelocity(client,newVel); } @@ -2140,9 +2156,9 @@ public Action:Command_ReloadConfig(client, args) { LoadPhysics(); LoadTimerSettings(); - + ReplyToCommand(client, "Timer: Settings reloaded."); - + return Plugin_Handled; } @@ -2153,7 +2169,7 @@ public Action:Command_NoclipMe(client, args) ReplyToCommand(client, "\x04[SM] \x05You need to be alive to use noclip"); return Plugin_Handled; } - + if(g_Settings[NoclipEnable]) { if (GetEntityMoveType(client) != MOVETYPE_NOCLIP && !Timer_IsPlayerTouchingZoneType(client, ZtAntiNoclip)) @@ -2170,7 +2186,7 @@ public Action:Command_NoclipMe(client, args) } } else ReplyToCommand(client, "You have not access to this command."); - + return Plugin_Handled; } @@ -2180,7 +2196,7 @@ public Action:Command_Colour(client, args) { return Plugin_Handled; } - + if (g_colourme[client] == 1) { g_colourme[client] = 0; @@ -2189,7 +2205,7 @@ public Action:Command_Colour(client, args) { g_colourme[client] = 1; } - + return Plugin_Handled; } @@ -2199,7 +2215,7 @@ public Action:Command_ToggleAuto(client, args) { return Plugin_Handled; } - + if (g_bAutoDisable[client]) { g_bAutoDisable[client] = false; @@ -2216,7 +2232,7 @@ public Action:Command_ToggleAuto(client, args) public Action:Timer_Push(Handle:timer, any:client) { Push_Client(client); - + return Plugin_Stop; } @@ -2232,7 +2248,7 @@ public Action:Timer_Boost(Handle:timer, any:client) { new style = Timer_GetStyle(client); Client_BoostForward(client, g_Physics[style][StyleBoostForward], g_Physics[style][StyleBoostForwardMax]); - + return Plugin_Stop; } @@ -2240,10 +2256,10 @@ Client_BoostForward(client, Float:scale, Float:maxspeed) { new Float:fVelocity[3]; GetEntPropVector(client, Prop_Data, "m_vecVelocity", fVelocity); - + fVelocity[0] = fVelocity[0]*scale; fVelocity[1] = fVelocity[1]*scale; - + if(maxspeed == 0.0 || SquareRoot(Pow(fVelocity[0],2.0)+Pow(fVelocity[1],2.0)) < maxspeed) { TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, fVelocity); @@ -2253,13 +2269,13 @@ Client_BoostForward(client, Float:scale, Float:maxspeed) PunishAbuse(client, type = -1) { new style = Timer_GetStyle(client); - + if(type == -1) type = g_Physics[style][StylePunishType]; - + if(type <= 0) return; - + //Block controls if(type == 1) { diff --git a/gameserver/addons/sourcemod/scripting/timer-rankings.sp b/gameserver/addons/sourcemod/scripting/timer-rankings.sp index c77968b..55a302f 100644 --- a/gameserver/addons/sourcemod/scripting/timer-rankings.sp +++ b/gameserver/addons/sourcemod/scripting/timer-rankings.sp @@ -1,3 +1,5 @@ +#pragma dynamic 131072 + #include #include #include @@ -551,17 +553,15 @@ public OnClientDisconnect(client) if(!g_iEnabled) return; - //g_sAuth[client][0] = '\0'; - if(g_bAuthed[client]) { new points, points_start; if(KvJumpToKey(g_hSession, g_sAuth[client], false)) { points_start = KvGetNum(g_hSession, "points", 0); - points = Timer_GetPoints(client); + points = g_iCurrentPoints[client]; } - + KvSetFloat(g_hSession, "disconnec_time", GetEngineTime()); new String:sPre[3]; @@ -575,8 +575,8 @@ public OnClientDisconnect(client) { GetArrayString(g_hCfgArray_DisplayChat, g_iCurrentIndex[client], sNameBuffer, sizeof(sNameBuffer)); } - - if(g_iPositionMethod == 2) + + if(g_iPositionMethod == 2 || points <= 0) { #if defined LEGACY_COLORS CFormat(sNameBuffer, 1024, client); @@ -605,9 +605,11 @@ public OnClientDisconnect(client) g_bLoadedCookies[client] = false; g_iNextIndex[client] = -1; + + g_iCurrentPoints[client] = -1; + g_iCurrentRank[client] = -1; g_iCurrentIndex[client] = -1; g_iCompletions[client] = 0; - g_iCurrentPoints[client] = -1; g_iLastGlobalMessage[client] = 0; g_iClientDisplay[client] = 0; } @@ -1613,7 +1615,7 @@ ShowConnectMsg(client) { #if defined LEGACY_COLORS CFormat(sNameBuffer, 1024, client); - CPrintToChatAll("%s%N {olive}[{lightred}%d points{olive}] connected from %s.", sNameBuffer, client, g_iCurrentPoints[client], s_Country); + CPrintToChatAll("%s%N: {default}rank {yellow}%d/%d {default}with {yellow}%d points {default}connected from {lightgreen}%s{default}.", sNameBuffer, client, g_iCurrentRank[client], g_iTotalPlayers, g_iCurrentPoints[client], s_Country); #else CReplaceColorCodes(sNameBuffer, client, false, 1024); CPrintToChatAll("%s%N {green}[{yellow}%d points{green}] connected from %s.", sNameBuffer, client, g_iCurrentPoints[client], s_Country); @@ -2596,9 +2598,16 @@ public Native_GetPointRank(Handle:plugin, numParams) public Native_GetTag(Handle:plugin, numParams) { - decl String:sTagBuffer[128]; - GetArrayString(g_hCfgArray_DisplayTag, g_iCurrentIndex[GetNativeCell(3)], sTagBuffer, sizeof(sTagBuffer)); - SetNativeString(1, sTagBuffer, GetNativeCell(2)); + if(g_iCurrentIndex[GetNativeCell(3)] != -1) + { + decl String:sTagBuffer[128]; + GetArrayString(g_hCfgArray_DisplayTag, g_iCurrentIndex[GetNativeCell(3)], sTagBuffer, sizeof(sTagBuffer)); + SetNativeString(1, sTagBuffer, GetNativeCell(2)); + } + else + { + SetNativeString(1, g_sLoadingChatTag, GetNativeCell(2)); + } } public Native_GetChatTag(Handle:plugin, numParams) diff --git a/gameserver/addons/sourcemod/scripting/timer-rankings_points_lite.sp b/gameserver/addons/sourcemod/scripting/timer-rankings_points_lite.sp index 85ebffa..67462ba 100644 --- a/gameserver/addons/sourcemod/scripting/timer-rankings_points_lite.sp +++ b/gameserver/addons/sourcemod/scripting/timer-rankings_points_lite.sp @@ -49,10 +49,7 @@ public OnTimerRecord(client, track, style, Float:time, Float:lasttime, currentra if(IsFakeClient(client)) return; - new tier; - if(track == TRACK_SHORT) - tier = 1; - else tier = Timer_GetTier(track); + new tier = Timer_GetTier(track); if(Timer_IsStyleRanked(style)) { diff --git a/gameserver/addons/sourcemod/scripting/timer-sound.sp b/gameserver/addons/sourcemod/scripting/timer-sound.sp index d208df0..2dcde18 100644 --- a/gameserver/addons/sourcemod/scripting/timer-sound.sp +++ b/gameserver/addons/sourcemod/scripting/timer-sound.sp @@ -9,23 +9,29 @@ #define MAX_FILE_LEN 128 -new Handle:Sound_TimerFinish = INVALID_HANDLE; -new String:SND_TIMER_FINISH[MAX_FILE_LEN]; +new Handle:g_hTimerFinish = INVALID_HANDLE; +new String:g_sTimerFinish[MAX_FILE_LEN]; +new bool:g_bTimerFinish = false; -new Handle:Sound_TimerResume = INVALID_HANDLE; -new String:SND_TIMER_RESUME[MAX_FILE_LEN]; +new Handle:g_hTimerResume = INVALID_HANDLE; +new String:g_sTimerResume[MAX_FILE_LEN]; +new bool:g_bTimerResume = false; -new Handle:Sound_TimerPause = INVALID_HANDLE; -new String:SND_TIMER_PAUSE[MAX_FILE_LEN]; +new Handle:g_hTimerPause = INVALID_HANDLE; +new String:g_sTimerPause[MAX_FILE_LEN]; +new bool:g_bTimerPause = false; -new Handle:Sound_TimerWorldRecord = INVALID_HANDLE; -new String:SND_TIMER_WORLDRECORD[MAX_FILE_LEN]; +new Handle:g_hTimerWorldRecord = INVALID_HANDLE; +new String:g_sTimerWorldRecord[MAX_FILE_LEN]; +new bool:g_bTimerWorldRecord = false; -new Handle:Sound_TimerWorldRecordAll = INVALID_HANDLE; -new String:SND_TIMER_WORLDRECORD_ALL[MAX_FILE_LEN]; +new Handle:g_hTimerWorldRecordAll = INVALID_HANDLE; +new String:g_sTimerWorldRecordAll[MAX_FILE_LEN]; +new bool:g_bTimerWorldRecordAll = false; -new Handle:Sound_TimerPersonalBest = INVALID_HANDLE; -new String:SND_TIMER_PERSONALBEST[MAX_FILE_LEN]; +new Handle:g_hTimerPersonalBest = INVALID_HANDLE; +new String:g_sTimerPersonalBest[MAX_FILE_LEN]; +new bool:g_bTimerPersonalBest = false; public Plugin:myinfo = { @@ -38,81 +44,114 @@ public Plugin:myinfo = public OnPluginStart() { - Sound_TimerFinish = CreateConVar("timer_sound_finish", "ui/freeze_cam.wav", ""); - Sound_TimerWorldRecord = CreateConVar("timer_sound_worldrecord", "ui/freeze_cam.wav", ""); - Sound_TimerWorldRecordAll = CreateConVar("timer_sound_worldrecord_all", "ui/freeze_cam.wav", ""); - Sound_TimerPause = CreateConVar("timer_sound_pause", "ui/freeze_cam.wav", ""); - Sound_TimerResume = CreateConVar("timer_sound_resume", "ui/freeze_cam.wav", ""); - Sound_TimerPersonalBest = CreateConVar("timer_sound_personalbest", "ui/freeze_cam.wav", ""); - - AutoExecConfig(true, "timer/timer-sounds"); + g_hTimerFinish = CreateConVar("timer_sound_finish", "ui/freeze_cam.wav", ""); + g_hTimerWorldRecord = CreateConVar("timer_sound_worldrecord", "ui/freeze_cam.wav", ""); + g_hTimerWorldRecordAll = CreateConVar("timer_sound_worldrecord_all", "ui/freeze_cam.wav", ""); + g_hTimerPause = CreateConVar("timer_sound_pause", "ui/freeze_cam.wav", ""); + g_hTimerResume = CreateConVar("timer_sound_resume", "ui/freeze_cam.wav", ""); + g_hTimerPersonalBest = CreateConVar("timer_sound_personalbest", "ui/freeze_cam.wav", ""); + + AutoExecConfig(true, "timer/timer-sounds"); } public OnConfigsExecuted() { - CacheSounds(); - Timer_LogTrace("[Sound] Sounds cached OnConfigsExecuted"); + CacheSounds(); + Timer_LogTrace("[Sound] Sounds cached OnConfigsExecuted"); } public CacheSounds() { - GetConVarString(Sound_TimerFinish, SND_TIMER_FINISH, sizeof(SND_TIMER_FINISH)); - PrepareSound(SND_TIMER_FINISH); - - GetConVarString(Sound_TimerPause, SND_TIMER_PAUSE, sizeof(SND_TIMER_PAUSE)); - PrepareSound(SND_TIMER_PAUSE); - - GetConVarString(Sound_TimerResume, SND_TIMER_RESUME, sizeof(SND_TIMER_RESUME)); - PrepareSound(SND_TIMER_FINISH); - - GetConVarString(Sound_TimerWorldRecord, SND_TIMER_WORLDRECORD, sizeof(SND_TIMER_WORLDRECORD)); - PrepareSound(SND_TIMER_WORLDRECORD); - - GetConVarString(Sound_TimerWorldRecordAll, SND_TIMER_WORLDRECORD_ALL, sizeof(SND_TIMER_WORLDRECORD_ALL)); - PrepareSound(SND_TIMER_WORLDRECORD_ALL); - - GetConVarString(Sound_TimerPersonalBest, SND_TIMER_PERSONALBEST, sizeof(SND_TIMER_PERSONALBEST)); - PrepareSound(SND_TIMER_PERSONALBEST); + GetConVarString(g_hTimerFinish, g_sTimerFinish, sizeof(g_sTimerFinish)); + GetConVarString(g_hTimerPause, g_sTimerPause, sizeof(g_sTimerPause)); + GetConVarString(g_hTimerResume, g_sTimerResume, sizeof(g_sTimerResume)); + GetConVarString(g_hTimerWorldRecord, g_sTimerWorldRecord, sizeof(g_sTimerWorldRecord)); + GetConVarString(g_hTimerWorldRecordAll, g_sTimerWorldRecordAll, sizeof(g_sTimerWorldRecordAll)); + GetConVarString(g_hTimerPersonalBest, g_sTimerPersonalBest, sizeof(g_sTimerPersonalBest)); + + if(GetEngineVersion() == Engine_CSGO && StrContains(g_sTimerFinish, ".mp3", false) || GetEngineVersion() == Engine_CSS && StrContains(g_sTimerFinish, ".mp3", false) || StrContains(g_sTimerFinish, ".wav", false)) + { + g_bTimerFinish = PrepareSound(g_sTimerFinish); + } + if(GetEngineVersion() == Engine_CSGO && StrContains(g_sTimerPause, ".mp3", false) || GetEngineVersion() == Engine_CSS && StrContains(g_sTimerPause, ".mp3", false) || StrContains(g_sTimerPause, ".wav", false)) + { + g_bTimerPause = PrepareSound(g_sTimerPause); + } + if(GetEngineVersion() == Engine_CSGO && StrContains(g_sTimerResume, ".mp3", false) || GetEngineVersion() == Engine_CSS && StrContains(g_sTimerResume, ".mp3", false) || StrContains(g_sTimerResume, ".wav", false)) + { + g_bTimerResume = PrepareSound(g_sTimerResume); + } + if(GetEngineVersion() == Engine_CSGO && StrContains(g_sTimerWorldRecord, ".mp3", false) || GetEngineVersion() == Engine_CSS && StrContains(g_sTimerWorldRecord, ".mp3", false) || StrContains(g_sTimerWorldRecord, ".wav", false)) + { + g_bTimerWorldRecord = PrepareSound(g_sTimerWorldRecord); + } + if(GetEngineVersion() == Engine_CSGO && StrContains(g_sTimerWorldRecordAll, ".mp3", false) || GetEngineVersion() == Engine_CSS && StrContains(g_sTimerWorldRecordAll, ".mp3", false) || StrContains(g_sTimerWorldRecordAll, ".wav", false)) + { + g_bTimerWorldRecordAll = PrepareSound(g_sTimerWorldRecordAll); + } + if(GetEngineVersion() == Engine_CSGO && StrContains(g_sTimerPersonalBest, ".mp3", false) || GetEngineVersion() == Engine_CSS && StrContains(g_sTimerPersonalBest, ".mp3", false) || StrContains(g_sTimerPersonalBest, ".wav", false)) + { + g_bTimerPersonalBest = PrepareSound(g_sTimerPersonalBest); + } } -public PrepareSound(String: sound[MAX_FILE_LEN]) +public bool:PrepareSound(String: sound[MAX_FILE_LEN]) { - decl String:fileSound[MAX_FILE_LEN]; + decl String:fileSound[MAX_FILE_LEN]; - FormatEx(fileSound, MAX_FILE_LEN, "sound/%s", sound); + FormatEx(fileSound, MAX_FILE_LEN, "sound/%s", sound); - if (FileExists(fileSound)) - { - PrecacheSoundAny(sound, true); - AddFileToDownloadsTable(fileSound); - Timer_LogTrace("[Sound] File '%s' added to downloads table.", fileSound); - } + if (FileExists(fileSound) && g_bTimerWorldRecord) + { + new bool:bReturn; + bReturn = PrecacheSoundAny(sound, true); + AddFileToDownloadsTable(fileSound); + Timer_LogTrace("[Sound] File '%s' added to downloads table.", fileSound); + + return bReturn; + } + return false; } public OnTimerPaused(client) { - EmitSoundToClientAny(client, SND_TIMER_PAUSE); + if(g_bTimerPause) + { + EmitSoundToClientAny(client, g_sTimerPause); + } } public OnTimerResumed(client) { - EmitSoundToClientAny(client, SND_TIMER_RESUME); + if(g_bTimerResume) + { + EmitSoundToClientAny(client, g_sTimerResume); + } } public OnTimerWorldRecord(client) { - //Stop the sound first - EmitSoundToAllAny(SND_TIMER_WORLDRECORD_ALL, _, _, _, SND_STOPLOOPING); - - EmitSoundToAllAny(SND_TIMER_WORLDRECORD_ALL); + if(g_bTimerWorldRecordAll) + { + //Stop the sound first + EmitSoundToAllAny(g_sTimerWorldRecordAll, _, _, _, SND_STOPLOOPING); + + EmitSoundToAllAny(g_sTimerWorldRecordAll); + } } public OnTimerPersonalRecord(client) { - EmitSoundToClientAny(client, SND_TIMER_PERSONALBEST); + if(g_bTimerPersonalBest) + { + EmitSoundToClientAny(client, g_sTimerPersonalBest); + } } public OnTimerRecord(client) { - EmitSoundToClientAny(client, SND_TIMER_FINISH); + if(g_bTimerFinish) + { + EmitSoundToClientAny(client, g_sTimerFinish); + } } diff --git a/gameserver/addons/sourcemod/scripting/timer-spec.sp b/gameserver/addons/sourcemod/scripting/timer-spec.sp index 3ee8887..d4fff6b 100644 --- a/gameserver/addons/sourcemod/scripting/timer-spec.sp +++ b/gameserver/addons/sourcemod/scripting/timer-spec.sp @@ -16,11 +16,10 @@ public Plugin:myinfo ={ }; public OnPluginStart() -{ +{ RegConsoleCmd("sm_spec", Command_spec, "sm_spec - Spectates a player."); RegConsoleCmd("sm_spectate", Command_spec, "sm_spectate - Spectates a player."); RegConsoleCmd("sm_specmost", Cmd_SpecMost); - RegConsoleCmd("sm_speclist", Cmd_SpecList); RegConsoleCmd("sm_specfar", Cmd_SpecFar); LoadTranslations("common.phrases"); } @@ -42,9 +41,9 @@ public Action:Command_spec(client, args) } new String:arg1[64]; GetCmdArgString(arg1, sizeof(arg1)); - + new target = FindTarget(client, arg1, true, true); - if (target == -1) + if (target == -1) { return Plugin_Handled; } @@ -71,9 +70,9 @@ public Action:Cmd_SpecMost(client, args) { if(i == client) continue; - - spectators = 0; - + + spectators = 0; + if(Client_IsValid(i, true)) { for(new x = 1; x <= MaxClients; x++) @@ -82,9 +81,9 @@ public Action:Cmd_SpecMost(client, args) { continue; } - + new SpecMode = GetEntProp(x, Prop_Send, "m_iObserverMode"); - + if(SpecMode == 4 || SpecMode == 5) { if(GetEntPropEnt(x, Prop_Send, "m_hObserverTarget") == target) @@ -108,64 +107,25 @@ public Action:Cmd_SpecMost(client, args) return Plugin_Handled; } -public Action:Cmd_SpecList(client, args) -{ - new spectators = 0, String:buffer[1024]; - - for(new i = 1; i <= MaxClients; i++) - { - if(i == client) - continue; - - if(Client_IsValid(i, true)) - { - // missing check for IsClientInGame in Client_IsValid? - if(IsClientInGame(i)) - { - new SpecMode = GetEntProp(i, Prop_Send, "m_iObserverMode"); - - if(SpecMode == 4 || SpecMode == 5) - { - if(GetEntPropEnt(i, Prop_Send, "m_hObserverTarget") == client) - { - spectators++; - if(spectators > 1) Format(buffer, sizeof(buffer), "%s, %N", buffer, i); - else Format(buffer, sizeof(buffer), "%N", i); - } - } - } - } - } - - if(spectators > 0) - { - PrintToChat(client, "[SPEC-LIST] You have %d spectators:", spectators); - PrintToChat(client, "%s.", buffer); - } - else PrintToChat(client, "[SPEC-LIST] Nobody is spectating you."); - - return Plugin_Handled; -} - public Action:Cmd_SpecFar(client, args) { new MaxLevel, Level, target, oldtarget; oldtarget = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); - + for(new i = 1; i <= MaxClients; i++) { if(i == client) continue; - + if(i == oldtarget) continue; - + if(!Client_IsValid(i, true)) continue; - + Level = Timer_GetClientLevel(i); - + if(Level > MaxLevel) { MaxLevel = Level; diff --git a/gameserver/addons/sourcemod/scripting/timer-teams.sp b/gameserver/addons/sourcemod/scripting/timer-teams.sp index ecc4047..27fb4fe 100644 --- a/gameserver/addons/sourcemod/scripting/timer-teams.sp +++ b/gameserver/addons/sourcemod/scripting/timer-teams.sp @@ -21,7 +21,6 @@ new String:g_currentMap[64]; new g_clientTeammate[MAXPLAYERS+1]=0; new bool:g_bClientCoop[MAXPLAYERS+1]; -new g_iCoopCountdown[MAXPLAYERS+1]; new bool:g_bClientChallenge[MAXPLAYERS+1]; new g_iChallengeCountdown[MAXPLAYERS+1]; @@ -41,10 +40,7 @@ new Handle:g_OnChallengeConfirm; new Handle:g_OnChallengeWin; new Handle:g_OnChallengeForceEnd; -new Handle:g_OnCoopStart; new Handle:g_OnCoopConfirm; -new Handle:g_OnCoopWin; -new Handle:g_OnCoopForceEnd; new Float:g_fLastRun[MAXPLAYERS+1]; @@ -64,28 +60,40 @@ public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) RegPluginLibrary("timer-teams"); CreateNative("Timer_GetChallengeStatus", Native_GetChallengeStatus); CreateNative("Timer_GetCoopStatus", Native_GetCoopStatus); - + CreateNative("Timer_GetClientTeammate", Native_GetClientTeammate); CreateNative("Timer_SetClientTeammate", Native_SetClientTeammate); - + return APLRes_Success; } public OnPluginStart() { g_timerPhysics = LibraryExists("timer-physics"); - + LoadPhysics(); LoadTimerSettings(); - + LoadTranslations("timer.phrases"); if(g_Settings[ChallengeEnable]) RegConsoleCmd("sm_challenge", Command_Challenge); - if(g_Settings[CoopEnable]) RegConsoleCmd("sm_coop", Command_Coop); + + if(g_Settings[CoopEnable]) + { + RegConsoleCmd("sm_coop", Command_Coop); + RegConsoleCmd("sm_partner", Command_Coop); + RegConsoleCmd("sm_mate", Command_Coop); + RegConsoleCmd("sm_party", Command_Coop); + + RegConsoleCmd("sm_uncoop", Command_UnCoop); + RegConsoleCmd("sm_unpartner", Command_UnCoop); + RegConsoleCmd("sm_unmate", Command_UnCoop); + RegConsoleCmd("sm_unparty", Command_UnCoop); + } Sound_ChallengeStart = CreateConVar("timer_sound_challenge_start", "ui/freeze_cam.wav", ""); Sound_TimerOwned = CreateConVar("timer_sound_owned", "ui/freeze_cam.wav", ""); - + HookConVarChange(Sound_ChallengeStart, Action_OnSettingsChange); HookConVarChange(Sound_TimerOwned, Action_OnSettingsChange); @@ -93,14 +101,11 @@ public OnPluginStart() g_OnChallengeStart = CreateGlobalForward("OnChallengeStart", ET_Event, Param_Cell,Param_Cell); g_OnChallengeWin = CreateGlobalForward("OnChallengeWin", ET_Event, Param_Cell,Param_Cell); g_OnChallengeForceEnd = CreateGlobalForward("OnChallengeForceEnd", ET_Event, Param_Cell,Param_Cell); - + g_OnCoopConfirm = CreateGlobalForward("OnCoopConfirm", ET_Event, Param_Cell,Param_Cell,Param_Cell); - g_OnCoopStart = CreateGlobalForward("OnCoopStart", ET_Event, Param_Cell,Param_Cell); - g_OnCoopWin = CreateGlobalForward("OnCoopWin", ET_Event, Param_Cell,Param_Cell); - g_OnCoopForceEnd = CreateGlobalForward("OnCoopForceEnd", ET_Event, Param_Cell,Param_Cell); - + AutoExecConfig(true, "timer/timer-teams"); - + HookEvent("player_spawn", Event_Reset); HookEvent("player_connect", Event_Reset); HookEvent("player_disconnect", Event_Reset); @@ -111,10 +116,10 @@ public OnPluginStart() public OnMapStart() { GetCurrentMap(g_currentMap, sizeof(g_currentMap)); - + LoadPhysics(); LoadTimerSettings(); - + for (new i = 1; i <= MaxClients; i++) { g_clientTeammate[i] = 0; @@ -132,7 +137,7 @@ public OnLibraryAdded(const String:name[]) } public OnLibraryRemoved(const String:name[]) -{ +{ if (StrEqual(name, "timer-physics")) { g_timerPhysics = false; @@ -148,7 +153,7 @@ public CacheSounds() { GetConVarString(Sound_ChallengeStart, SND_CHALLENGE_START, sizeof(SND_CHALLENGE_START)); PrepareSound(SND_CHALLENGE_START); - + GetConVarString(Sound_TimerOwned, SND_TIMER_OWNED, sizeof(SND_TIMER_OWNED)); PrepareSound(SND_TIMER_OWNED); } @@ -196,21 +201,19 @@ public OnClientStartTouchZoneType(client, MapZoneType:type) { if(!client) return; - + new mate = Timer_GetClientTeammate(client); - + if(!mate) return; - + if(!g_bClientChallenge[client] && !g_bClientCoop[client]) return; - + if (type == ZtEnd) { - if(g_bClientChallenge[client]) + if(g_bClientChallenge[client]) EndChallenge(client, 0); - else if (g_bClientCoop[client] && Timer_IsPlayerTouchingZoneType(mate, ZtEnd)) - EndCoop(client, 0); } } @@ -218,15 +221,15 @@ public OnClientEndTouchZoneType(client, MapZoneType:type) { if(!client) return; - + new mate = Timer_GetClientTeammate(client); - + if(!mate) return; - + if(!g_bClientChallenge[client] && !g_bClientCoop[client]) return; - + if (type == ZtStart) { if(g_Settings[CoopOnly]) @@ -244,7 +247,7 @@ public Action:Command_Challenge(client, args) { if(!client) return Plugin_Handled; - + if(g_bClientCoop[client]) { CPrintToChat(client, "%s You are already challenging.", PLUGIN_PREFIX2); @@ -253,12 +256,12 @@ public Action:Command_Challenge(client, args) { CPrintToChat(client, "%s You are already in coop mode.", PLUGIN_PREFIX2); } - else + else { new Handle:menu = CreateMenu(Handle_PointSelectMenu); - + SetMenuTitle(menu, "Select bet"); - + decl String:buffer[32]; FormatEx(buffer, sizeof(buffer), "%d", g_Settings[ChallengeBet1]); AddMenuItem(menu, buffer, "Very Low"); @@ -270,13 +273,13 @@ public Action:Command_Challenge(client, args) AddMenuItem(menu, buffer, "Pro"); FormatEx(buffer, sizeof(buffer), "%d", g_Settings[ChallengeBet5]); AddMenuItem(menu, buffer, "Match"); - + DisplayMenu(menu, client, MENU_TIME_FOREVER); } - + return Plugin_Handled; } - + public Handle_PointSelectMenu(Handle:menu, MenuAction:action, client, itemNum) { if ( action == MenuAction_Select ) @@ -292,50 +295,50 @@ public Handle_PointSelectMenu(Handle:menu, MenuAction:action, client, itemNum) } Menu_SelectChallengeMate(client) -{ +{ new Handle:menu = CreateMenu(MenuHandlerChallenge); SetMenuTitle(menu, "Select your opponent"); - + new iCount = 0; - + for (new i = 1; i <= MaxClients; i++) { if(!Client_IsValid(i)) { continue; } - + if(IsFakeClient(i)) { continue; } - + if(client == i) { continue; } - + if(g_bClientCoop[i]) { continue; } - + if(g_bClientChallenge[i]) { continue; } - + if(GetGameTime() < g_fIgnoreTime[i]) { continue; } - + decl String:name2[32]; FormatEx(name2, sizeof(name2), "%N", i); decl String:zone2[32]; FormatEx(zone2,sizeof(zone2),"%d", i); AddMenuItem(menu, zone2, name2); - + iCount++; } @@ -344,7 +347,7 @@ Menu_SelectChallengeMate(client) CPrintToChat(client, "%s No Target found.", PLUGIN_PREFIX2); return; } - + SetMenuExitButton(menu, true); DisplayMenu(menu, client, 20); } @@ -356,18 +359,18 @@ public MenuHandlerChallenge(Handle:menu, MenuAction:action, creator, param2) decl String:info[100], String:info2[100]; new bool:found = GetMenuItem(menu, param2, info, sizeof(info), _, info2, sizeof(info2)); new client = StringToInt(info); - + if(IsFakeClient(client)) { StartChallenge(client, creator); - + Call_StartForward(g_OnChallengeConfirm); Call_PushCell(client); Call_PushCell(creator); Call_PushCell(g_iBet[creator]); Call_Finish(); } - + if(found) { if(IsClientInGame(client)) @@ -378,12 +381,12 @@ public MenuHandlerChallenge(Handle:menu, MenuAction:action, creator, param2) SetMenuTitle(menu2, "Confirm Challenge with %N on style: %s.", creator, g_Physics[Timer_GetStyle(creator)][StyleName]); } else SetMenuTitle(menu2, "Confirm Challenge with %N.", creator); - + decl String:name[32]; FormatEx(name, sizeof(name),"%d", creator); AddMenuItem(menu2, name, "Yes"); AddMenuItem(menu2, "no", "no"); - + SetMenuExitButton(menu, true); DisplayMenu(menu2, client, 20); } @@ -398,29 +401,29 @@ public MenuHandlerChallengeConfirm(Handle:menu, MenuAction:action, client, param decl String:info[100], String:info2[100]; new bool:found = GetMenuItem(menu, param2, info, sizeof(info), _, info2, sizeof(info2)); new target = StringToInt(info); - + if(!target || target <= 0) { CPrintToChat(client, "%s Invalid target. Something went wrong, sry.", PLUGIN_PREFIX2); return; } - + if(StrEqual(info, "no")) { g_fIgnoreTime[client] = GetGameTime()+g_Settings[ChallengeIgnoreCooldown]; if(g_Settings[ChallengeIgnoreCooldown] > 0) CPrintToChat(client, "%s You can't be challenged next %ds.", PLUGIN_PREFIX2, RoundToFloor(g_Settings[ChallengeIgnoreCooldown])); - - if(IsClientInGame(target)) - if(g_Settings[ChallengeIgnoreCooldown] > 0) + + if(IsClientInGame(target)) + if(g_Settings[ChallengeIgnoreCooldown] > 0) CPrintToChat(target, "%s %N rejected your challenge request. You have to wait %ds to ask for a new challenge", PLUGIN_PREFIX2, client, RoundToFloor(g_Settings[ChallengeIgnoreCooldown])); - else + else CPrintToChat(target, "%s %N rejected your challenge request.", PLUGIN_PREFIX2, client); } else if(found) { g_iBet[client] = g_iBet[target]; StartChallenge(client, target); - + Call_StartForward(g_OnChallengeConfirm); Call_PushCell(client); Call_PushCell(target); @@ -434,25 +437,25 @@ StartChallenge(client, target) { FakeClientCommand(client, "sm_start"); FakeClientCommand(target, "sm_start"); - + Timer_SetClientTeammate(client, target, 1); Timer_SetStyle(client, Timer_GetStyle(target)); - + SetEntityMoveType(client, MOVETYPE_NONE); SetEntityMoveType(target, MOVETYPE_NONE); - + Timer_SetClientHide(client, 1); Timer_SetClientHide(target, 1); - + g_iChallengeCountdown[client] = 5; g_iChallengeCountdown[target] = 5; - + g_fLastRun[client] = 0.0; g_fLastRun[client] = 0.0; - + Timer_SetTrack(client, TRACK_NORMAL); Timer_SetTrack(target, TRACK_NORMAL); - + g_bClientChallenge[client] = true; g_bClientChallenge[target] = true; @@ -464,11 +467,11 @@ public Action:ChallengeCountdown(Handle:timer, any:client) { if(!IsClientInGame(client)) return Plugin_Stop; - + PrintCenterText(client, "%d", g_iChallengeCountdown[client]); - + g_iChallengeCountdown[client]--; - + if(g_iChallengeCountdown[client] <= 0) { PrintCenterText(client, "GO GO GO !!!"); @@ -476,20 +479,20 @@ public Action:ChallengeCountdown(Handle:timer, any:client) EmitSoundToClient(client, SND_CHALLENGE_START); SetEntityMoveType(client, MOVETYPE_WALK); new mate = Timer_GetClientTeammate(client); - + Call_StartForward(g_OnChallengeStart); Call_PushCell(client); Call_PushCell(mate); Call_Finish(); - + Timer_Start(client); Timer_Start(mate); - + new Float:time = GetGameTime(); - + g_fStartTime[client] = time; g_fStartTime[mate] = time; - + return Plugin_Stop; } @@ -501,9 +504,9 @@ public Action:Command_Coop(client, args) new Handle:menu = CreateMenu(MenuHandlerCoop); SetMenuTitle(menu, "Teammate Select"); //new bool:isadmin = Client_IsAdmin(client); - + new iCount = 0; - + //show rest for (new i = 1; i <= MaxClients; i++) { @@ -523,25 +526,25 @@ public Action:Command_Coop(client, args) { continue; } - + decl String:name2[32]; FormatEx(name2, sizeof(name2), "%N", i); decl String:zone2[32]; FormatEx(zone2,sizeof(zone2),"%d", i); AddMenuItem(menu, zone2, name2); - + iCount++; } - + if(iCount == 0) { CPrintToChat(client, "%s No Target found.", PLUGIN_PREFIX2); return Plugin_Handled; } - + SetMenuExitButton(menu, true); DisplayMenu(menu, client, 20); - + return Plugin_Handled; } @@ -565,12 +568,12 @@ public MenuHandlerCoop(Handle:menu, MenuAction:action, client, param2) new Handle:menu2 = CreateMenu(MenuHandlerCoopConfirm); SetMenuTitle(menu2, "Confirm Coop-Modus with %N", client); //new bool:isadmin = Client_IsAdmin(client); - + decl String:xclient[32]; FormatEx(xclient, sizeof(xclient),"%d", client); AddMenuItem(menu2, xclient, "Yes"); AddMenuItem(menu2, "no", "no"); - + SetMenuExitButton(menu, true); DisplayMenu(menu2, target, 20); } @@ -588,10 +591,10 @@ public MenuHandlerCoopConfirm(Handle:menu, MenuAction:action, client, param2) new target = StringToInt(info); if(StrEqual(info, "no")) { - + } else if(found) - { + { if(!target || target <= 0) { } @@ -600,7 +603,7 @@ public MenuHandlerCoopConfirm(Handle:menu, MenuAction:action, client, param2) StartCoop(client, target); } } - + Call_StartForward(g_OnCoopConfirm); Call_PushCell(client); Call_PushCell(target); @@ -612,57 +615,33 @@ public MenuHandlerCoopConfirm(Handle:menu, MenuAction:action, client, param2) StartCoop(client, target) { Timer_SetClientTeammate(client, target, 1); + Timer_SetTrack(client, Timer_GetTrack(target)); - - SetEntityMoveType(client, MOVETYPE_NONE); - SetEntityMoveType(target, MOVETYPE_NONE); - - g_iCoopCountdown[client] = 5; - g_iCoopCountdown[target] = 5; - - Timer_SetTrack(client, TRACK_NORMAL); - Timer_SetTrack(target, TRACK_NORMAL); - - g_bClientCoop[client] = false; - g_bClientCoop[target] = false; - CreateTimer(1.0, CoopCountdown, client, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); - CreateTimer(1.0, CoopCountdown, target, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); + Timer_ClientTeleportLevel(client, LEVEL_START); + Timer_ClientTeleportLevel(target, LEVEL_START); + + g_bClientCoop[client] = true; + g_bClientCoop[target] = true; } -public Action:CoopCountdown(Handle:timer, any:client) +public Action:Command_UnCoop(client, args) { - if(!IsClientInGame(client)) - return Plugin_Stop; - - PrintCenterText(client, "%d", g_iCoopCountdown[client]); - - g_iCoopCountdown[client]--; - - SetEntityMoveType(client, MOVETYPE_NONE); + new mate = g_clientTeammate[client]; + + g_clientTeammate[client] = 0; + g_clientTeammate[mate] = 0; + + Timer_SetTrack(client, TRACK_NORMAL); + Timer_SetTrack(mate, TRACK_NORMAL); + Timer_ClientTeleportLevel(client, LEVEL_START); - - if(g_iCoopCountdown[client] <= 0) - { - PrintCenterText(client, "GO GO GO !!!"); - SetEntityMoveType(client, MOVETYPE_WALK); - new mate = Timer_GetClientTeammate(client); - - g_bClientCoop[client] = true; - g_bClientCoop[mate] = true; - - Call_StartForward(g_OnCoopStart); - Call_PushCell(client); - Call_PushCell(mate); - Call_Finish(); - - Timer_Start(client); - Timer_Start(mate); - - return Plugin_Stop; - } + Timer_ClientTeleportLevel(mate, LEVEL_START); - return Plugin_Continue; + g_bClientCoop[client] = false; + g_bClientCoop[mate] = false; + + return Plugin_Handled; } new Float:g_fLastFail[MAXPLAYERS+1]; @@ -672,7 +651,7 @@ public Action:EndChallenge(client, force) new mate = Timer_GetClientTeammate(client); new Float:fTime = GetGameTime(); new bool:fake_death = false; - + if(g_bClientChallenge[client] && g_bClientChallenge[mate]) { //Failed? @@ -681,17 +660,17 @@ public Action:EndChallenge(client, force) if(fTime - g_fLastFail[client] > 1.0) { g_fLastFail[client] = fTime; - + Call_StartForward(g_OnChallengeForceEnd); Call_PushCell(client); Call_PushCell(mate); Call_Finish(); - + if(fTime - g_fStartTime[mate] > g_Settings[ChallengeAbortTime]) { CPrintToChat(client, "%s You have surrendered this challenge.", PLUGIN_PREFIX2); CPrintToChat(mate, "%s %N has surrendered this challenge.", PLUGIN_PREFIX2, client); - + EndChallenge(mate, 2); //Mate Wins } else @@ -702,78 +681,78 @@ public Action:EndChallenge(client, force) } else { - + } } //We have a winner else if(force == 0) { - decl String:pname[32], String:pname2[32]; - + decl String:pname[32], String:pname2[32]; + FormatEx(pname, sizeof(pname), "%N", client); FormatEx(pname2, sizeof(pname2), "%N", mate); - + //Play sounds EmitSoundToClient(client, SND_TIMER_OWNED); EmitSoundToClient(mate, SND_TIMER_OWNED); - + new bool:enabled = false; new jumps = 0; new Float:time; new fpsmax; - + if (g_Settings[ChallengeSaveRecords] && Timer_GetClientTimer(client, enabled, time, jumps, fpsmax)) { new style = 0; if (g_timerPhysics) style = Timer_GetStyle(client); - + Timer_FinishRound(client, g_currentMap, time, jumps, style, fpsmax, 0); } - + //Forward Call_StartForward(g_OnChallengeWin); Call_PushCell(client); Call_PushCell(mate); Call_Finish(); - + fake_death = true; } else if(force == 2) { - decl String:pname[32], String:pname2[32]; - + decl String:pname[32], String:pname2[32]; + FormatEx(pname, sizeof(pname), "%N", client); FormatEx(pname2, sizeof(pname2), "%N", mate); - + //Play sounds EmitSoundToClient(client, SND_TIMER_OWNED); EmitSoundToClient(mate, SND_TIMER_OWNED); - + //Forward Call_StartForward(g_OnChallengeWin); Call_PushCell(client); Call_PushCell(mate); Call_Finish(); - + fake_death = true; } } - + //end challenge g_bClientChallenge[client] = false; g_bClientChallenge[mate] = false; - + //dissolve team Timer_SetClientTeammate(client, 0, 0); Timer_SetClientTeammate(mate, 0, 0); - + //Reset hide Timer_SetClientHide(client, 0); Timer_SetClientHide(mate, 0); - + g_fLastRun[client] = fTime; - + if(fake_death) { //Fake death event @@ -786,63 +765,9 @@ public Action:EndChallenge(client, force) FireEvent(event, false); } } - - Timer_Reset(client); - Timer_Reset(mate); -} -public Action:EndCoop(client, force) -{ - new mate = Timer_GetClientTeammate(client); - - if(g_bClientCoop[client] && g_bClientCoop[mate]) - { - decl String:pname[32], String:pname2[32]; - - FormatEx(pname, sizeof(pname), "%N", client); - FormatEx(pname2, sizeof(pname2), "%N", mate); - - if (force == 1) - { - PrintToChatAll(PLUGIN_PREFIX, "Coop Fail", pname, pname2); - - Call_StartForward(g_OnCoopForceEnd); - Call_PushCell(client); - Call_PushCell(mate); - Call_Finish(); - } - else if (force == 0) - { - PrintToChatAll(PLUGIN_PREFIX, "Coop Win", pname, pname2); - - Call_StartForward(g_OnCoopWin); - Call_PushCell(client); - Call_PushCell(mate); - Call_Finish(); - - new bool:enabled; //tier running - new jumps; //current jump count - new fpsmax; //fps settings - new bool:track = false; //track timer running - new Float:time; //current time - - new style = Timer_GetStyle(client); - - Timer_GetClientTimer(client, enabled, time, jumps, fpsmax); - - Timer_FinishRound(client, g_currentMap, time, jumps, style, fpsmax, track); - Timer_FinishRound(mate, g_currentMap, time, jumps, style, fpsmax, track); - } - } - - g_bClientCoop[client] = false; - g_bClientCoop[mate] = false; - Timer_Reset(client); Timer_Reset(mate); - - Timer_SetClientTeammate(client, 0, 0); - Timer_SetClientTeammate(mate, 0, 0); } public OnTimerStopped(client) @@ -868,17 +793,13 @@ public OnTimerReseted(client) ForceEnd(client) { new mate = Timer_GetClientTeammate(client); - + if(mate != 0) { - if(g_bClientChallenge[client]) + if(g_bClientChallenge[client]) { EndChallenge(client,1); } - else if (g_bClientCoop[client]) - { - EndCoop(client,1); - } } } @@ -892,32 +813,32 @@ public Native_SetClientTeammate(Handle:plugin, numParams) new client = GetNativeCell(1); new mate = GetNativeCell(2); new bool:teleport = bool:GetNativeCell(2); - + if(0 < client) { //Make sure there are no issues with other mates new oldcmate = g_clientTeammate[client]; new oldmmate = g_clientTeammate[mate]; - + g_clientTeammate[oldcmate] = 0; g_clientTeammate[oldmmate] = 0; g_clientTeammate[client] = 0; g_clientTeammate[mate] = 0; - + if(0 < mate) { g_clientTeammate[client] = mate; g_clientTeammate[mate] = client; } - + if(teleport) { Timer_ClientTeleportLevel(client, LEVEL_START); Timer_ClientTeleportLevel(mate, LEVEL_START); - + if(oldcmate && oldcmate != mate) Timer_ClientTeleportLevel(oldcmate, LEVEL_START); - + if(oldmmate && oldmmate != client) Timer_ClientTeleportLevel(oldmmate, LEVEL_START); } @@ -932,4 +853,4 @@ public Native_GetChallengeStatus(Handle:plugin, numParams) public Native_GetCoopStatus(Handle:plugin, numParams) { return g_bClientCoop[GetNativeCell(1)]; -} \ No newline at end of file +} diff --git a/gameserver/addons/sourcemod/scripting/timer-teleme.sp b/gameserver/addons/sourcemod/scripting/timer-teleme.sp index d3cb428..dc55857 100644 --- a/gameserver/addons/sourcemod/scripting/timer-teleme.sp +++ b/gameserver/addons/sourcemod/scripting/timer-teleme.sp @@ -23,9 +23,9 @@ public OnPluginStart() { LoadPhysics(); LoadTimerSettings(); - + g_timerMapzones = LibraryExists("timer-mapzones"); - + RegConsoleCmd("sm_teleme", Command_TeleMe); RegConsoleCmd("sm_tpto", Command_TeleMe); RegConsoleCmd("sm_teleport", Command_TeleMe); @@ -42,7 +42,7 @@ public OnLibraryAdded(const String:name[]) } public OnLibraryRemoved(const String:name[]) -{ +{ if(StrEqual(name, "timer-mapzones")) { g_timerMapzones = false; @@ -57,20 +57,23 @@ public OnMapStart() public Action:Command_TeleMe(client, args) { - if(IsPlayerAlive(client) && g_Settings[PlayerTeleportEnable]) + if(!g_Settings[PlayerTeleportEnable]) + CPrintToChat(client, "%s This command has been disabled.", PLUGIN_PREFIX2); + + if(IsPlayerAlive(client)) { - if(!g_Settings[PlayerTeleportEnable]) + if(!g_Settings[PlayerTeleportEnable]) { ReplyToCommand(client, "Teleport disabled by server."); return Plugin_Handled; } - + new Handle:menu = CreateMenu(MenuHandlerTeleMe); SetMenuTitle(menu, "Teleport to selected player"); //new bool:isadmin = Client_IsAdmin(client); - + new iCount = 0; - + //show rest for (new i = 1; i <= MaxClients; i++) { @@ -78,19 +81,19 @@ public Action:Command_TeleMe(client, args) { continue; } - + decl String:name2[32]; - if(g_timerMapzones) + if(g_timerMapzones) FormatEx(name2, sizeof(name2), "%N Stage: %d", i, Timer_GetClientLevel(i)); - else + else FormatEx(name2, sizeof(name2), "%N", i); - + decl String:zone2[32]; FormatEx(zone2,sizeof(zone2),"%d", i); AddMenuItem(menu, zone2, name2); iCount++; } - + if(iCount > 0) { SetMenuExitButton(menu, true); @@ -102,7 +105,7 @@ public Action:Command_TeleMe(client, args) { CPrintToChat(client, "%s You have to be alive", PLUGIN_PREFIX2); } - + return Plugin_Handled; } @@ -122,7 +125,7 @@ public MenuHandlerTeleMe(Handle:menu, MenuAction:action, client, param2) new Float:origin[3], Float:angles[3]; GetClientAbsOrigin(target, origin); GetClientAbsAngles(target, angles); - + //Do not reset his pretty timer if it can be paused if (g_Settings[PauseEnable]) { @@ -131,8 +134,8 @@ public MenuHandlerTeleMe(Handle:menu, MenuAction:action, client, param2) else { Timer_Reset(client); - } - + } + TeleportEntity(client, origin, angles, NULL_VECTOR); } } diff --git a/gameserver/addons/sourcemod/scripting/timer-worldrecord.sp b/gameserver/addons/sourcemod/scripting/timer-worldrecord.sp index 4f012f8..92a76af 100644 --- a/gameserver/addons/sourcemod/scripting/timer-worldrecord.sp +++ b/gameserver/addons/sourcemod/scripting/timer-worldrecord.sp @@ -5,10 +5,15 @@ #include #include -#include #include #include +#undef REQUIRE_PLUGIN +#include +#include +#include +#include + //Max. number of records per style to cache /** @@ -53,14 +58,14 @@ enum RecordStats /** * New World Record Cache */ - + new Handle:g_hCache[MAX_STYLES][MAX_TRACKS]; new nCacheTemplate[RecordCache]; /** * Old World Record Cache */ - + //new g_cache[MAX_STYLES][3][MAX_CACHE][RecordCache]; /** @@ -89,6 +94,7 @@ new g_iAdminSelectedStyle[MAXPLAYERS+1]; new g_iAdminSelectedTrack[MAXPLAYERS+1]; new bool:g_timerPhysics = false; +new bool:g_timerStrafes = false; new Handle:g_OnRecordCacheLoaded; @@ -104,7 +110,7 @@ public Plugin:myinfo = public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max) { RegPluginLibrary("timer-worldrecord"); - + CreateNative("Timer_ForceReloadCache", Native_ForceReloadCache); CreateNative("Timer_GetStyleRecordWRStats", Native_GetStyleRecordWRStats); CreateNative("Timer_GetStyleRank", Native_GetStyleRank); @@ -132,43 +138,44 @@ public OnPluginStart() { LoadPhysics(); LoadTimerSettings(); - + ConnectSQL(true); - + g_timerPhysics = LibraryExists("timer-physics"); - + g_timerStrafes = LibraryExists("timer-strafes"); + LoadTranslations("timer.phrases"); - + RegConsoleCmd("sm_top", Command_WorldRecord); RegConsoleCmd("sm_wr", Command_WorldRecord); - if(g_Settings[BonusWrEnable]) + if(g_Settings[BonusWrEnable]) { RegConsoleCmd("sm_btop", Command_BonusWorldRecord); RegConsoleCmd("sm_topb", Command_BonusWorldRecord); RegConsoleCmd("sm_bwr", Command_BonusWorldRecord); RegConsoleCmd("sm_wrb", Command_BonusWorldRecord); - + RegConsoleCmd("sm_b2top", Command_Bonus2WorldRecord); RegConsoleCmd("sm_topb2", Command_Bonus2WorldRecord); RegConsoleCmd("sm_b2wr", Command_Bonus2WorldRecord); RegConsoleCmd("sm_wrb2", Command_Bonus2WorldRecord); - + RegConsoleCmd("sm_b3top", Command_Bonus3WorldRecord); RegConsoleCmd("sm_topb3", Command_Bonus3WorldRecord); RegConsoleCmd("sm_b3wr", Command_Bonus3WorldRecord); RegConsoleCmd("sm_wrb3", Command_Bonus3WorldRecord); - + RegConsoleCmd("sm_b4top", Command_Bonus4WorldRecord); RegConsoleCmd("sm_topb4", Command_Bonus4WorldRecord); RegConsoleCmd("sm_b4wr", Command_Bonus4WorldRecord); RegConsoleCmd("sm_wrb4", Command_Bonus4WorldRecord); - + RegConsoleCmd("sm_b5top", Command_Bonus5WorldRecord); RegConsoleCmd("sm_topb5", Command_Bonus5WorldRecord); RegConsoleCmd("sm_b5wr", Command_Bonus5WorldRecord); RegConsoleCmd("sm_wrb5", Command_Bonus5WorldRecord); } - + RegConsoleCmd("sm_record", Command_PersonalRecord); RegConsoleCmd("sm_rank", Command_PersonalRecord); //RegConsoleCmd("sm_delete", Command_Delete); @@ -177,18 +184,18 @@ public OnPluginStart() RegAdminCmd("sm_deleterecord_map", Command_DeletePlayerRecord_Map, ADMFLAG_ROOT, "sm_deleterecord_map STEAM_ID"); RegAdminCmd("sm_deleterecord", Command_DeletePlayerRecord_ID, ADMFLAG_RCON, "sm_deleterecord RECORDID"); RegAdminCmd("sm_deletemaprecords", Command_DeleteMapRecords_All, ADMFLAG_RCON, "sm_deleterecord MAPNAME"); - + AutoExecConfig(true, "timer/timer-worldrecord"); - + new Handle:topmenu; if (LibraryExists("adminmenu") && ((topmenu = GetAdminTopMenu()) != INVALID_HANDLE)) { OnAdminMenuReady(topmenu); } - + g_OnRecordCacheLoaded = CreateGlobalForward("OnRecordCacheLoaded", ET_Event, Param_Cell, Param_Cell); - for(new i = 0; i < MAX_STYLES-1; i++) + for(new i = 0; i < MAX_STYLES-1; i++) { if(!StrEqual(g_Physics[i][StyleQuickWrCommand], "")) { @@ -221,7 +228,7 @@ public OnPluginStart() AddCommandListener(Hook_WrCommands, g_Physics[i][StyleQuickBonus5WrCommand]); } } - + CacheReset(); } @@ -230,15 +237,23 @@ public OnLibraryAdded(const String:name[]) if (StrEqual(name, "timer-physics")) { g_timerPhysics = true; - } + } + else if (StrEqual(name, "timer-strafes")) + { + g_timerStrafes = true; + } } public OnLibraryRemoved(const String:name[]) -{ +{ if (StrEqual(name, "timer-physics")) { g_timerPhysics = false; } + else if (StrEqual(name, "timer-strafes")) + { + g_timerStrafes = false; + } else if (StrEqual(name, "adminmenu")) { hTopMenu = INVALID_HANDLE; @@ -248,10 +263,10 @@ public OnLibraryRemoved(const String:name[]) public OnMapStart() { GetCurrentMap(g_currentMap, sizeof(g_currentMap)); - + LoadPhysics(); LoadTimerSettings(); - + CacheReset(); RefreshCache(); } @@ -265,14 +280,14 @@ UpdateRanks() { if (g_hSQL == INVALID_HANDLE) return; - - for(new track = 0; track < MAX_TRACKS; track++) + + for(new track = 0; track < MAX_TRACKS; track++) { - for(new style = 0; style < g_StyleCount; style++) + for(new style = 0; style < g_StyleCount; style++) { if(!g_Physics[style][StyleEnable]) continue; - + if(g_Physics[style][StyleCategory] == MCategory_Ranked) { decl String:query[2048]; @@ -300,57 +315,57 @@ public Action:Command_WorldRecord(client, args) CreateRankedWRMenu(client); else CreateWRMenu(client, g_StyleDefault, TRACK_NORMAL); - + return Plugin_Handled; } public Action:Command_BonusWorldRecord(client, args) { if (g_timerPhysics && g_Settings[MultimodeEnable]) - CreateRankedBWRMenu(client, 1); + CreateRankedBWRMenu(client, TRACK_BONUS); else CreateWRMenu(client, g_StyleDefault, TRACK_BONUS); - + return Plugin_Handled; } public Action:Command_Bonus2WorldRecord(client, args) { if (g_timerPhysics && g_Settings[MultimodeEnable]) - CreateRankedBWRMenu(client, 2); + CreateRankedBWRMenu(client, TRACK_BONUS2); else - CreateWRMenu(client, g_StyleDefault, TRACK_BONUS); - + CreateWRMenu(client, g_StyleDefault, TRACK_BONUS2); + return Plugin_Handled; } public Action:Command_Bonus3WorldRecord(client, args) { if (g_timerPhysics && g_Settings[MultimodeEnable]) - CreateRankedBWRMenu(client, 3); + CreateRankedBWRMenu(client, TRACK_BONUS3); else - CreateWRMenu(client, g_StyleDefault, TRACK_BONUS); - + CreateWRMenu(client, g_StyleDefault, TRACK_BONUS3); + return Plugin_Handled; } public Action:Command_Bonus4WorldRecord(client, args) { if (g_timerPhysics && g_Settings[MultimodeEnable]) - CreateRankedBWRMenu(client, 4); + CreateRankedBWRMenu(client, TRACK_BONUS4); else - CreateWRMenu(client, g_StyleDefault, TRACK_BONUS); - + CreateWRMenu(client, g_StyleDefault, TRACK_BONUS4); + return Plugin_Handled; } public Action:Command_Bonus5WorldRecord(client, args) { if (g_timerPhysics && g_Settings[MultimodeEnable]) - CreateRankedBWRMenu(client, 5); + CreateRankedBWRMenu(client, TRACK_BONUS5); else - CreateWRMenu(client, g_StyleDefault, TRACK_BONUS); - + CreateWRMenu(client, g_StyleDefault, TRACK_BONUS5); + return Plugin_Handled; } @@ -360,14 +375,14 @@ public Action:Hook_WrCommands(client, const String:sCommand[], argc) { return Plugin_Continue; } - for(new i = 0; i < MAX_STYLES-1; i++) + for(new i = 0; i < MAX_STYLES-1; i++) { if(!g_Physics[i][StyleEnable]) continue; - + if(g_Physics[i][StyleCategory] != MCategory_Ranked) continue; - + if(!StrEqual(g_Physics[i][StyleQuickWrCommand], "") && StrEqual(g_Physics[i][StyleQuickWrCommand], sCommand)) { CreateWRMenu(client, i, TRACK_NORMAL); @@ -399,7 +414,7 @@ public Action:Hook_WrCommands(client, const String:sCommand[], argc) return Plugin_Handled; } } - + return Plugin_Continue; } @@ -418,7 +433,7 @@ public Action:Command_PersonalRecord(client, args) { new argsCount = GetCmdArgs(); new target = -1; - + if (argsCount == 0) { @@ -428,7 +443,7 @@ public Action:Command_PersonalRecord(client, args) { decl String:name[64]; GetCmdArg(1, name, sizeof(name)); - + new targets[2]; decl String:targetName[32]; new bool:ml = false; @@ -444,26 +459,26 @@ public Action:Command_PersonalRecord(client, args) else { new style = Timer_GetStyle(client); - + new track = Timer_GetTrack(client); - + decl String:auth[32]; GetClientAuthString(target, auth, sizeof(auth)); - + for (new i = 0; i < GetArraySize(g_hCache[style][track]); i++) { new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], i, nCache[0]); - + if (StrEqual(nCache[Auth], auth)) { g_wrStyleMode[client] = style; - CreatePlayerInfoMenu(client, nCache[Id], track); + CreateRecordInfoMenu(client, i, track); break; } - } + } } - + return Plugin_Handled; } @@ -488,18 +503,18 @@ public Action:Command_DeletePlayerRecord_All(client, args) FormatEx(query, sizeof(query), "DELETE FROM round WHERE auth = '%s'", auth); SQL_TQuery(g_hSQL, DeleteRecordsCallback, query, _, DBPrio_Normal); - + return Plugin_Handled; } public Action:Command_DeletePlayerRecord_Map(client, args) -{ +{ if (args < 1) { ReplyToCommand(client, "Usage: sm_deleterecord_map "); return Plugin_Handled; } - + new String:auth[32]; GetCmdArgString(auth, sizeof(auth)); @@ -507,18 +522,18 @@ public Action:Command_DeletePlayerRecord_Map(client, args) FormatEx(query, sizeof(query), "DELETE FROM round WHERE auth = '%s' AND map = '%s'", auth, g_currentMap); SQL_TQuery(g_hSQL, DeleteRecordsCallback, query, _, DBPrio_Normal); - + return Plugin_Handled; } public Action:Command_DeletePlayerRecord_ID(client, args) -{ +{ if (args < 1) { ReplyToCommand(client, "Usage: sm_deleterecord "); return Plugin_Handled; } - + new String:id[32]; GetCmdArgString(id, sizeof(id)); @@ -526,18 +541,18 @@ public Action:Command_DeletePlayerRecord_ID(client, args) FormatEx(query, sizeof(query), "DELETE FROM round WHERE id = '%s'", id); SQL_TQuery(g_hSQL, DeleteRecordsCallback, query, _, DBPrio_Normal); - + return Plugin_Handled; } public Action:Command_DeleteMapRecords_All(client, args) -{ +{ if (args < 1) { ReplyToCommand(client, "Usage: sm_deleterecord "); return Plugin_Handled; } - + new String:mapname[32]; GetCmdArgString(mapname, sizeof(mapname)); @@ -545,7 +560,7 @@ public Action:Command_DeleteMapRecords_All(client, args) FormatEx(query, sizeof(query), "DELETE FROM round WHERE map = '%s'", mapname); SQL_TQuery(g_hSQL, DeleteRecordsCallback, query, _, DBPrio_Normal); - + return Plugin_Handled; } @@ -566,26 +581,26 @@ public OnAdminMenuReady(Handle:topmenu) if (topmenu == hTopMenu) { return; } - + // Save the Handle hTopMenu = topmenu; - + if ((oMapZoneMenu = FindTopMenuCategory(topmenu, "Timer Records")) == INVALID_TOPMENUOBJECT) { oMapZoneMenu = AddToTopMenu(hTopMenu,"Timer Records",TopMenuObject_Category,AdminMenu_CategoryHandler,INVALID_TOPMENUOBJECT); } - + AddToTopMenu(hTopMenu, "timer_delete",TopMenuObject_Item,AdminMenu_DeleteRecord, oMapZoneMenu,"timer_delete",ADMFLAG_RCON); - + AddToTopMenu(hTopMenu, "timer_deletemaprecords",TopMenuObject_Item,AdminMenu_DeleteMapRecords, oMapZoneMenu,"timer_deletemaprecords",ADMFLAG_RCON); - - AddToTopMenu(hTopMenu, "sm_reloadcache", TopMenuObject_Item,AdminMenu_ReloadCache, + + AddToTopMenu(hTopMenu, "sm_reloadcache", TopMenuObject_Item,AdminMenu_ReloadCache, oMapZoneMenu, "sm_reloadcache",ADMFLAG_CHANGEMAP); } -public AdminMenu_CategoryHandler(Handle:topmenu, +public AdminMenu_CategoryHandler(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, @@ -599,7 +614,7 @@ public AdminMenu_CategoryHandler(Handle:topmenu, } } -public AdminMenu_DeleteMapRecords(Handle:topmenu, +public AdminMenu_DeleteMapRecords(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, param, @@ -611,40 +626,40 @@ public AdminMenu_DeleteMapRecords(Handle:topmenu, } else if (action == TopMenuAction_SelectOption) { decl String:map[32]; GetCurrentMap(map, sizeof(map)); - + if(param == 0) DeleteMapRecords(map); else DeleteMapRecordsMenu(param); } } -public AdminMenu_ReloadCache(Handle:topmenu, +public AdminMenu_ReloadCache(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, client, String:buffer[], maxlength) { - if (action == TopMenuAction_DisplayOption) + if (action == TopMenuAction_DisplayOption) { FormatEx(buffer, maxlength, "Refresh Cache"); - } else if (action == TopMenuAction_SelectOption) + } else if (action == TopMenuAction_SelectOption) { CPrintToChatAll(PLUGIN_PREFIX, "Word Record Cache Loaded"); RefreshCache(); } } -public AdminMenu_DeleteRecord(Handle:topmenu, +public AdminMenu_DeleteRecord(Handle:topmenu, TopMenuAction:action, TopMenuObject:object_id, client, String:buffer[], maxlength) { - if (action == TopMenuAction_DisplayOption) + if (action == TopMenuAction_DisplayOption) { FormatEx(buffer, maxlength, "Delete Single Record"); - } else if (action == TopMenuAction_SelectOption) + } else if (action == TopMenuAction_SelectOption) { if(g_Settings[MultimodeEnable]) CreateAdminModeSelection(client); else CreateAdminTrackSelection(client); @@ -656,21 +671,21 @@ DeleteMapRecordsMenu(client) if (0 < client < MaxClients) { new Handle:menu = CreateMenu(Handle_DeleteMapRecordsMenu); - + SetMenuTitle(menu, "Are you sure!"); - - AddMenuItem(menu, "no", "Oh no"); + AddMenuItem(menu, "no", "Oh no"); AddMenuItem(menu, "no", "Oh no"); - AddMenuItem(menu, "yes", "!!! YES DELETE ALL RECORDS !!!"); AddMenuItem(menu, "no", "Oh no"); + AddMenuItem(menu, "yes", "!!! YES DELETE ALL RECORDS !!!"); AddMenuItem(menu, "no", "Oh no"); AddMenuItem(menu, "no", "Oh no"); - + AddMenuItem(menu, "no", "Oh no"); + DisplayMenu(menu, client, MENU_TIME_FOREVER); } } - + public Handle_DeleteMapRecordsMenu(Handle:menu, MenuAction:action, client, itemNum) { if ( action == MenuAction_Select ) @@ -695,38 +710,38 @@ CreateAdminModeSelection(client) SetMenuTitle(menu, "Select Style"); SetMenuExitButton(menu, true); - + new items = 0; - - for(new i = 0; i < MAX_STYLES-1; i++) + + for(new i = 0; i < MAX_STYLES-1; i++) { if(!g_Physics[i][StyleEnable]) continue; - + decl String:text[92]; FormatEx(text, sizeof(text), "%s", g_Physics[i][StyleName]); - + decl String:text2[32]; FormatEx(text2, sizeof(text2), "%d", i); - + AddMenuItem(menu, text2, text); items++; } - + if(items > 0) DisplayMenu(menu, client, MENU_TIME_FOREVER); else CloseHandle(menu); } public MenuHandler_AdminModeSelection(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { RefreshCache(); CloseHandle(menu); } - else if (action == MenuAction_Select) + else if (action == MenuAction_Select) { - decl String:info[32]; + decl String:info[32]; GetMenuItem(menu, itemNum, info, sizeof(info)); g_iAdminSelectedStyle[client] = StringToInt(info); CreateAdminTrackSelection(client); @@ -739,32 +754,32 @@ CreateAdminTrackSelection(client) SetMenuTitle(menu, "Select Style"); SetMenuExitButton(menu, true); - + AddMenuItem(menu, "0", "Normal"); - if(Timer_GetMapzoneCount(ZtBonusStart) > 0) + if(Timer_GetMapzoneCount(ZtBonusStart) > 0) AddMenuItem(menu, "1", "Bonus"); - if(Timer_GetMapzoneCount(ZtBonus2Start) > 0) + if(Timer_GetMapzoneCount(ZtBonus2Start) > 0) AddMenuItem(menu, "2", "Bonus 2"); - if(Timer_GetMapzoneCount(ZtBonus3Start) > 0) + if(Timer_GetMapzoneCount(ZtBonus3Start) > 0) AddMenuItem(menu, "3", "Bonus 3"); - if(Timer_GetMapzoneCount(ZtBonus4Start) > 0) + if(Timer_GetMapzoneCount(ZtBonus4Start) > 0) AddMenuItem(menu, "4", "Bonus 4"); - if(Timer_GetMapzoneCount(ZtBonus5Start) > 0) + if(Timer_GetMapzoneCount(ZtBonus5Start) > 0) AddMenuItem(menu, "5", "Bonus 5"); - + DisplayMenu(menu, client, MENU_TIME_FOREVER); } public MenuHandler_AdminTrackSelection(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { RefreshCache(); CloseHandle(menu); } - else if (action == MenuAction_Select) + else if (action == MenuAction_Select) { - decl String:info[32]; + decl String:info[32]; GetMenuItem(menu, itemNum, info, sizeof(info)); g_iAdminSelectedTrack[client] = StringToInt(info); CreateAdminRecordSelection(client, g_iAdminSelectedStyle[client], g_iAdminSelectedTrack[client]); @@ -777,21 +792,21 @@ CreateAdminRecordSelection(client, style, track) SetMenuTitle(menu, "Select Record"); SetMenuExitButton(menu, true); - - new items = 0; - - + + new items = 0; + + for (new i = 0; i < GetArraySize(g_hCache[style][track]); i++) { new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], i, nCache[0]); - + if (nCache[Ignored]) continue; - + decl String:text[92]; FormatEx(text, sizeof(text), "%s - %s", nCache[TimeString], nCache[Name]); - + if (g_Settings[JumpsEnable]) Format(text, sizeof(text), "%s (%d %T)", text, nCache[Jumps], "Jumps", client); @@ -812,20 +827,20 @@ CreateAdminRecordSelection(client, style, track) public MenuHandler_SelectPlayer(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Select) + else if (action == MenuAction_Select) { - decl String:info[32]; + decl String:info[32]; GetMenuItem(menu, itemNum, info, sizeof(info)); - + decl String:query[512]; FormatEx(query, sizeof(query), "DELETE FROM `round` WHERE id = '%s'", info); SQL_TQuery(g_hSQL, DeletePlayersRecordCallback, query, client, DBPrio_Normal); - + RefreshCache(); } } @@ -837,15 +852,15 @@ public DeletePlayersRecordCallback(Handle:owner, Handle:hndl, const String:error Timer_LogError("SQL Error on DeletePlayerRecord: %s", error); return; } - + CreateAdminModeSelection(client); } -DeleteMapRecords(const String:map[]) +DeleteMapRecords(const String:map[]) { decl String:query[128]; - FormatEx(query, sizeof(query), "DELETE FROM `round` WHERE map = '%s'", map); + FormatEx(query, sizeof(query), "DELETE FROM `round` WHERE map = '%s'", map); SQL_TQuery(g_hSQL, DeleteRecordsCallback, query, _, DBPrio_Normal); } @@ -857,37 +872,37 @@ RefreshCache() ConnectSQL(true); } else - { + { for (new style = 0; style < MAX_STYLES-1; style++) { if(!g_Physics[style][StyleEnable]) continue; if(g_Physics[style][StyleCategory] != MCategory_Ranked) continue; - + g_cacheLoaded[style][0] = false; g_cacheLoaded[style][1] = false; g_cacheLoaded[style][2] = false; - + decl String:query[512]; - FormatEx(query, sizeof(query), "SELECT id, auth, time, jumps, style, name, date, finishcount, stage, rank, jumpacc, finishspeed, maxspeed, avgspeed, strafes, strafeacc, replaypath, custom1, custom2, custom3 FROM round WHERE map = '%s' AND style = %d AND track = %d ORDER BY time ASC;", g_currentMap, style, TRACK_NORMAL); + FormatEx(query, sizeof(query), "SELECT id, auth, time, jumps, style, name, date, finishcount, stage, rank, jumpacc, finishspeed, maxspeed, avgspeed, strafes, strafeacc, replaypath, custom1, custom2, custom3 FROM round WHERE map = '%s' AND style = %d AND track = %d ORDER BY time ASC;", g_currentMap, style, TRACK_NORMAL); SQL_TQuery(g_hSQL, RefreshCacheCallback, query, style, DBPrio_Low); - + if(g_Settings[BonusWrEnable]) { - FormatEx(query, sizeof(query), "SELECT id, auth, time, jumps, style, name, date, finishcount, stage, rank, jumpacc, finishspeed, maxspeed, avgspeed, strafes, strafeacc, replaypath, custom1, custom2, custom3 FROM round WHERE map = '%s' AND style = %d AND track = %d ORDER BY time ASC;", g_currentMap, style, TRACK_BONUS); + FormatEx(query, sizeof(query), "SELECT id, auth, time, jumps, style, name, date, finishcount, stage, rank, jumpacc, finishspeed, maxspeed, avgspeed, strafes, strafeacc, replaypath, custom1, custom2, custom3 FROM round WHERE map = '%s' AND style = %d AND track = %d ORDER BY time ASC;", g_currentMap, style, TRACK_BONUS); SQL_TQuery(g_hSQL, RefreshBonusCacheCallback, query, style, DBPrio_Low); - - FormatEx(query, sizeof(query), "SELECT id, auth, time, jumps, style, name, date, finishcount, stage, rank, jumpacc, finishspeed, maxspeed, avgspeed, strafes, strafeacc, replaypath, custom1, custom2, custom3 FROM round WHERE map = '%s' AND style = %d AND track = %d ORDER BY time ASC;", g_currentMap, style, TRACK_BONUS2); + + FormatEx(query, sizeof(query), "SELECT id, auth, time, jumps, style, name, date, finishcount, stage, rank, jumpacc, finishspeed, maxspeed, avgspeed, strafes, strafeacc, replaypath, custom1, custom2, custom3 FROM round WHERE map = '%s' AND style = %d AND track = %d ORDER BY time ASC;", g_currentMap, style, TRACK_BONUS2); SQL_TQuery(g_hSQL, RefreshBonus2CacheCallback, query, style, DBPrio_Low); - - FormatEx(query, sizeof(query), "SELECT id, auth, time, jumps, style, name, date, finishcount, stage, rank, jumpacc, finishspeed, maxspeed, avgspeed, strafes, strafeacc, replaypath, custom1, custom2, custom3 FROM round WHERE map = '%s' AND style = %d AND track = %d ORDER BY time ASC;", g_currentMap, style, TRACK_BONUS3); + + FormatEx(query, sizeof(query), "SELECT id, auth, time, jumps, style, name, date, finishcount, stage, rank, jumpacc, finishspeed, maxspeed, avgspeed, strafes, strafeacc, replaypath, custom1, custom2, custom3 FROM round WHERE map = '%s' AND style = %d AND track = %d ORDER BY time ASC;", g_currentMap, style, TRACK_BONUS3); SQL_TQuery(g_hSQL, RefreshBonus3CacheCallback, query, style, DBPrio_Low); - - FormatEx(query, sizeof(query), "SELECT id, auth, time, jumps, style, name, date, finishcount, stage, rank, jumpacc, finishspeed, maxspeed, avgspeed, strafes, strafeacc, replaypath, custom1, custom2, custom3 FROM round WHERE map = '%s' AND style = %d AND track = %d ORDER BY time ASC;", g_currentMap, style, TRACK_BONUS4); + + FormatEx(query, sizeof(query), "SELECT id, auth, time, jumps, style, name, date, finishcount, stage, rank, jumpacc, finishspeed, maxspeed, avgspeed, strafes, strafeacc, replaypath, custom1, custom2, custom3 FROM round WHERE map = '%s' AND style = %d AND track = %d ORDER BY time ASC;", g_currentMap, style, TRACK_BONUS4); SQL_TQuery(g_hSQL, RefreshBonus4CacheCallback, query, style, DBPrio_Low); - - FormatEx(query, sizeof(query), "SELECT id, auth, time, jumps, style, name, date, finishcount, stage, rank, jumpacc, finishspeed, maxspeed, avgspeed, strafes, strafeacc, replaypath, custom1, custom2, custom3 FROM round WHERE map = '%s' AND style = %d AND track = %d ORDER BY time ASC;", g_currentMap, style, TRACK_BONUS5); + + FormatEx(query, sizeof(query), "SELECT id, auth, time, jumps, style, name, date, finishcount, stage, rank, jumpacc, finishspeed, maxspeed, avgspeed, strafes, strafeacc, replaypath, custom1, custom2, custom3 FROM round WHERE map = '%s' AND style = %d AND track = %d ORDER BY time ASC;", g_currentMap, style, TRACK_BONUS5); SQL_TQuery(g_hSQL, RefreshBonus5CacheCallback, query, style, DBPrio_Low); } } @@ -897,11 +912,11 @@ RefreshCache() CollectCache(track, style, Handle:hndl) { CacheResetSingle(track, style); - + while (SQL_FetchRow(hndl)) { new nNewCache[RecordCache]; - + nNewCache[Id] = SQL_FetchInt(hndl, 0); SQL_FetchString(hndl, 1, nNewCache[Auth], 32); nNewCache[Time] = SQL_FetchFloat(hndl, 2); @@ -914,7 +929,7 @@ CollectCache(track, style, Handle:hndl) nNewCache[Stage] = SQL_FetchInt(hndl, 8); nNewCache[CurrentRank] = SQL_FetchInt(hndl, 9); nNewCache[JumpAcc] = SQL_FetchFloat(hndl, 10); - + nNewCache[FinishSpeed] = SQL_FetchFloat(hndl, 11); nNewCache[MaxSpeed] = SQL_FetchFloat(hndl, 12); nNewCache[AvgSpeed] = SQL_FetchFloat(hndl, 13); @@ -924,14 +939,14 @@ CollectCache(track, style, Handle:hndl) SQL_FetchString(hndl, 17, nNewCache[Custom1], 32); SQL_FetchString(hndl, 18, nNewCache[Custom2], 32); SQL_FetchString(hndl, 19, nNewCache[Custom3], 32); - + nNewCache[Ignored] = false; - + PushArrayArray(g_hCache[style][track], nNewCache[0]); } - + g_cacheLoaded[style][track] = true; - + /* Forwards */ Call_StartForward(g_OnRecordCacheLoaded); Call_PushCell(style); @@ -948,7 +963,7 @@ public RefreshCacheCallback(Handle:owner, Handle:hndl, const String:error[], any Timer_LogError("SQL Error on RefreshCache: %s", error); return; } - + CollectCache(TRACK_NORMAL, style, hndl); } @@ -959,7 +974,7 @@ public RefreshBonusCacheCallback(Handle:owner, Handle:hndl, const String:error[] Timer_LogError("SQL Error on RefreshBonusCache: %s", error); return; } - + CollectCache(TRACK_BONUS, style, hndl); } @@ -970,7 +985,7 @@ public RefreshBonus2CacheCallback(Handle:owner, Handle:hndl, const String:error[ Timer_LogError("SQL Error on RefreshBonus2Cache: %s", error); return; } - + CollectCache(TRACK_BONUS2, style, hndl); } @@ -981,7 +996,7 @@ public RefreshBonus3CacheCallback(Handle:owner, Handle:hndl, const String:error[ Timer_LogError("SQL Error on RefreshBonus3Cache: %s", error); return; } - + CollectCache(TRACK_BONUS3, style, hndl); } @@ -992,7 +1007,7 @@ public RefreshBonus4CacheCallback(Handle:owner, Handle:hndl, const String:error[ Timer_LogError("SQL Error on RefreshBonus4Cache: %s", error); return; } - + CollectCache(TRACK_BONUS4, style, hndl); } @@ -1003,7 +1018,7 @@ public RefreshBonus5CacheCallback(Handle:owner, Handle:hndl, const String:error[ Timer_LogError("SQL Error on RefreshBonus5Cache: %s", error); return; } - + CollectCache(TRACK_BONUS5, style, hndl); } @@ -1014,17 +1029,17 @@ CollectBestCache(track, any:style) g_cachestats[style][track][RecordStatsBestTime] = 0.0; FormatEx(g_cachestats[style][track][RecordStatsName], 32, ""); FormatEx(g_cachestats[style][track][RecordStatsBestTimeString], 32, ""); - + for (new i = 0; i < GetArraySize(g_hCache[style][track]); i++) { new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], i, nCache[0]); - + if(nCache[Time] <= 0.0) continue; - + g_cachestats[style][track][RecordStatsCount]++; - + if(g_cachestats[style][track][RecordStatsBestTime] == 0.0 || g_cachestats[style][track][RecordStatsBestTime] > nCache[Time]) { g_cachestats[style][track][RecordStatsID] = nCache[Id]; @@ -1041,9 +1056,9 @@ ConnectSQL(bool:refreshCache) { CloseHandle(g_hSQL); } - + g_hSQL = INVALID_HANDLE; - + if (SQL_CheckConfig("timer")) { SQL_TConnect(ConnectSQLCallback, "timer", refreshCache); @@ -1059,7 +1074,7 @@ public ConnectSQLCallback(Handle:owner, Handle:hndl, const String:error[], any:d if (hndl == INVALID_HANDLE) { Timer_LogError("Connection to SQL database has failed, Reason: %s", error); - + g_reconnectCounter++; if (g_reconnectCounter >= 5) { @@ -1067,13 +1082,13 @@ public ConnectSQLCallback(Handle:owner, Handle:hndl, const String:error[], any:d //SetFailState("PLUGIN STOPPED - Reason: reconnect counter reached max - PLUGIN STOPPED"); //return; } - + ConnectSQL(data); return; } g_hSQL = CloneHandle(hndl); - + decl String:driver[16]; SQL_GetDriverIdent(owner, driver, sizeof(driver)); @@ -1081,7 +1096,7 @@ public ConnectSQLCallback(Handle:owner, Handle:hndl, const String:error[], any:d if (data) { - RefreshCache(); + RefreshCache(); } } @@ -1092,31 +1107,31 @@ CreateRankedWRMenu(client) new Handle:menu = CreateMenu(MenuHandler_RankedWR); SetMenuTitle(menu, "%t", "World Record Menu Title", client); - + SetMenuExitBackButton(menu, true); SetMenuExitButton(menu, true); - + new count = 0; new found = 0; - + new maxorder[3] = {0, ...}; - for(new i = 0; i < MAX_STYLES-1; i++) + for(new i = 0; i < MAX_STYLES-1; i++) { if(!g_Physics[i][StyleEnable]) continue; if(g_Physics[i][StyleCategory] != MCategory_Ranked) continue; - + if(g_Physics[i][StyleOrder] > maxorder[MCategory_Ranked]) maxorder[MCategory_Ranked] = g_Physics[i][StyleOrder]; - + count++; } - - for(new order = 0; order <= maxorder[MCategory_Ranked]; order++) + + for(new order = 0; order <= maxorder[MCategory_Ranked]; order++) { - for(new i = 0; i < MAX_STYLES-1; i++) + for(new i = 0; i < MAX_STYLES-1; i++) { if(!g_Physics[i][StyleEnable]) continue; @@ -1124,15 +1139,15 @@ CreateRankedWRMenu(client) continue; if(g_Physics[i][StyleOrder] != order) continue; - + found++; - + new String:buffer[8]; IntToString(i, buffer, sizeof(buffer)); - + AddMenuItem(menu, buffer, g_Physics[i][StyleName]); } - + if(found == count) break; } @@ -1143,15 +1158,15 @@ CreateRankedWRMenu(client) public MenuHandler_RankedWR(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Select) + else if (action == MenuAction_Select) { - decl String:info[8]; + decl String:info[8]; GetMenuItem(menu, itemNum, info, sizeof(info)); - + CreateWRMenu(client, StringToInt(info), 0); } } @@ -1181,33 +1196,33 @@ CreateRankedBWRMenu(client, track) { menu = CreateMenu(MenuHandler_RankedB5WR); } - + SetMenuTitle(menu, "%t", "Bonus World Record Menu Title", client); - + SetMenuExitBackButton(menu, true); SetMenuExitButton(menu, true); - + new count = 0; new found = 0; - + new maxorder[3] = {0, ...}; - for(new i = 0; i < MAX_STYLES-1; i++) + for(new i = 0; i < MAX_STYLES-1; i++) { if(!g_Physics[i][StyleEnable]) continue; if(g_Physics[i][StyleCategory] != MCategory_Ranked) continue; - + if(g_Physics[i][StyleOrder] > maxorder[MCategory_Ranked]) maxorder[MCategory_Ranked] = g_Physics[i][StyleOrder]; - + count++; } - - for(new order = 0; order <= maxorder[MCategory_Ranked]; order++) + + for(new order = 0; order <= maxorder[MCategory_Ranked]; order++) { - for(new i = 0; i < MAX_STYLES-1; i++) + for(new i = 0; i < MAX_STYLES-1; i++) { if(!g_Physics[i][StyleEnable]) continue; @@ -1215,15 +1230,15 @@ CreateRankedBWRMenu(client, track) continue; if(g_Physics[i][StyleOrder] != order) continue; - + found++; - + new String:buffer[8]; IntToString(i, buffer, sizeof(buffer)); - + AddMenuItem(menu, buffer, g_Physics[i][StyleName]); } - + if(found == count) break; } @@ -1234,91 +1249,76 @@ CreateRankedBWRMenu(client, track) public MenuHandler_RankedBWR(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Select) + else if (action == MenuAction_Select) { - decl String:info[32]; + decl String:info[32]; GetMenuItem(menu, itemNum, info, sizeof(info)); - - CreateWRMenu(client, StringToInt(info), 1); + + CreateWRMenu(client, StringToInt(info), TRACK_BONUS); } } public MenuHandler_RankedB2WR(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Select) + else if (action == MenuAction_Select) { - decl String:info[32]; + decl String:info[32]; GetMenuItem(menu, itemNum, info, sizeof(info)); - - CreateWRMenu(client, StringToInt(info), 2); + + CreateWRMenu(client, StringToInt(info), TRACK_BONUS2); } } public MenuHandler_RankedB3WR(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Select) + else if (action == MenuAction_Select) { - decl String:info[32]; + decl String:info[32]; GetMenuItem(menu, itemNum, info, sizeof(info)); - - CreateWRMenu(client, StringToInt(info), 3); + + CreateWRMenu(client, StringToInt(info), TRACK_BONUS3); } } public MenuHandler_RankedB4WR(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Select) + else if (action == MenuAction_Select) { - decl String:info[32]; + decl String:info[32]; GetMenuItem(menu, itemNum, info, sizeof(info)); - - CreateWRMenu(client, StringToInt(info), 4); + + CreateWRMenu(client, StringToInt(info), TRACK_BONUS4); } } public MenuHandler_RankedB5WR(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Select) + else if (action == MenuAction_Select) { - decl String:info[32]; + decl String:info[32]; GetMenuItem(menu, itemNum, info, sizeof(info)); - - CreateWRMenu(client, StringToInt(info), 5); - } -} -public MenuHandler_RankedSWR(Handle:menu, MenuAction:action, client, itemNum) -{ - if (action == MenuAction_End) - { - CloseHandle(menu); - } - else if (action == MenuAction_Select) - { - decl String:info[32]; - GetMenuItem(menu, itemNum, info, sizeof(info)); - - CreateWRMenu(client, StringToInt(info), 2); + CreateWRMenu(client, StringToInt(info), TRACK_BONUS5); } } @@ -1327,59 +1327,59 @@ CreateWRMenu(client, style, track) new Handle:menu; new total = GetArraySize(g_hCache[style][track]); - + if(track == TRACK_NORMAL) { menu = CreateMenu(MenuHandler_WR); SetMenuTitle(menu, "Top players on %s [%d total]", g_currentMap, total); } - else if (track == TRACK_BONUS) + else if (track == TRACK_BONUS) { menu = CreateMenu(MenuHandler_BonusWR); SetMenuTitle(menu, "Bonus-Top players on %s [%d total]", g_currentMap, total); } - else if (track == TRACK_BONUS2) + else if (track == TRACK_BONUS2) { menu = CreateMenu(MenuHandler_Bonus2WR); SetMenuTitle(menu, "Bonus2-Top players on %s [%d total]", g_currentMap, total); } - else if (track == TRACK_BONUS3) + else if (track == TRACK_BONUS3) { menu = CreateMenu(MenuHandler_Bonus3WR); SetMenuTitle(menu, "Bonus3-Top players on %s [%d total]", g_currentMap, total); } - else if (track == TRACK_BONUS4) + else if (track == TRACK_BONUS4) { menu = CreateMenu(MenuHandler_Bonus4WR); SetMenuTitle(menu, "Bonus4-Top players on %s [%d total]", g_currentMap, total); } - else if (track == TRACK_BONUS5) + else if (track == TRACK_BONUS5) { menu = CreateMenu(MenuHandler_Bonus5WR); SetMenuTitle(menu, "Bonus5-Top players on %s [%d total]", g_currentMap, total); } - + if (g_timerPhysics && g_Settings[MultimodeEnable]) SetMenuExitBackButton(menu, true); else SetMenuExitButton(menu, true); - + new items = 0; - + for (new i = 0; i < GetArraySize(g_hCache[style][track]); i++) { new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], i, nCache[0]); - + decl String:id[64]; - IntToString(nCache[Id], id, sizeof(id)); - + IntToString(i, id, sizeof(id)); + decl String:text[92]; FormatEx(text, sizeof(text), "#%d | %s - %s", i+1, nCache[Name], nCache[TimeString]); - + if (g_Settings[JumpsEnable]) Format(text, sizeof(text), "%s (%d jumps)", text, nCache[Jumps]); - + AddMenuItem(menu, id, text); items++; } @@ -1387,13 +1387,13 @@ CreateWRMenu(client, style, track) if (items == 0) { CloseHandle(menu); - + if (style == -1) - CPrintToChat(client, PLUGIN_PREFIX, "No Records"); + CPrintToChat(client, PLUGIN_PREFIX, "No Records"); else { CPrintToChat(client, PLUGIN_PREFIX, "No Difficulty Records"); - + if(g_Settings[MultimodeEnable]) { if(track == TRACK_NORMAL) CreateRankedWRMenu(client); @@ -1410,142 +1410,142 @@ CreateWRMenu(client, style, track) public MenuHandler_WR(Handle:menu, MenuAction:action, param1, param2) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Cancel) + else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack) + if (param2 == MenuCancel_ExitBack) { if (g_timerPhysics) CreateRankedWRMenu(param1); } - } - else if (action == MenuAction_Select) + } + else if (action == MenuAction_Select) { - decl String:info[64]; + decl String:info[64]; GetMenuItem(menu, param2, info, sizeof(info)); - CreatePlayerInfoMenu(param1, StringToInt(info), 0); + CreateRecordInfoMenu(param1, StringToInt(info), TRACK_NORMAL); } } public MenuHandler_BonusWR(Handle:menu, MenuAction:action, param1, param2) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Cancel) + else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack) + if (param2 == MenuCancel_ExitBack) { if (g_timerPhysics) - CreateRankedBWRMenu(param1, 1); + CreateRankedBWRMenu(param1, TRACK_BONUS); } - } - else if (action == MenuAction_Select) + } + else if (action == MenuAction_Select) { - decl String:info[64]; + decl String:info[64]; GetMenuItem(menu, param2, info, sizeof(info)); - - CreatePlayerInfoMenu(param1, StringToInt(info), 1); + + CreateRecordInfoMenu(param1, StringToInt(info), TRACK_BONUS); } } public MenuHandler_Bonus2WR(Handle:menu, MenuAction:action, param1, param2) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Cancel) + else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack) + if (param2 == MenuCancel_ExitBack) { if (g_timerPhysics) - CreateRankedBWRMenu(param1, 2); + CreateRankedBWRMenu(param1, TRACK_BONUS2); } - } - else if (action == MenuAction_Select) + } + else if (action == MenuAction_Select) { - decl String:info[64]; + decl String:info[64]; GetMenuItem(menu, param2, info, sizeof(info)); - - CreatePlayerInfoMenu(param1, StringToInt(info), 2); + + CreateRecordInfoMenu(param1, StringToInt(info), TRACK_BONUS2); } } public MenuHandler_Bonus3WR(Handle:menu, MenuAction:action, param1, param2) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Cancel) + else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack) + if (param2 == MenuCancel_ExitBack) { if (g_timerPhysics) - CreateRankedBWRMenu(param1, 3); + CreateRankedBWRMenu(param1, TRACK_BONUS3); } - } - else if (action == MenuAction_Select) + } + else if (action == MenuAction_Select) { - decl String:info[64]; + decl String:info[64]; GetMenuItem(menu, param2, info, sizeof(info)); - - CreatePlayerInfoMenu(param1, StringToInt(info), 3); + + CreateRecordInfoMenu(param1, StringToInt(info), TRACK_BONUS3); } } public MenuHandler_Bonus4WR(Handle:menu, MenuAction:action, param1, param2) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Cancel) + else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack) + if (param2 == MenuCancel_ExitBack) { if (g_timerPhysics) - CreateRankedBWRMenu(param1, 4); + CreateRankedBWRMenu(param1, TRACK_BONUS4); } - } - else if (action == MenuAction_Select) + } + else if (action == MenuAction_Select) { - decl String:info[64]; + decl String:info[64]; GetMenuItem(menu, param2, info, sizeof(info)); - - CreatePlayerInfoMenu(param1, StringToInt(info), 4); + + CreateRecordInfoMenu(param1, StringToInt(info), TRACK_BONUS4); } } public MenuHandler_Bonus5WR(Handle:menu, MenuAction:action, param1, param2) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Cancel) + else if (action == MenuAction_Cancel) { - if (param2 == MenuCancel_ExitBack) + if (param2 == MenuCancel_ExitBack) { if (g_timerPhysics) - CreateRankedBWRMenu(param1, 5); + CreateRankedBWRMenu(param1, TRACK_BONUS5); } - } - else if (action == MenuAction_Select) + } + else if (action == MenuAction_Select) { - decl String:info[64]; + decl String:info[64]; GetMenuItem(menu, param2, info, sizeof(info)); - - CreatePlayerInfoMenu(param1, StringToInt(info), 5); + + CreateRecordInfoMenu(param1, StringToInt(info), TRACK_BONUS5); } } -CreatePlayerInfoMenu(client, id, track) +CreateRecordInfoMenu(client, index, track) { new Handle:menu; @@ -1573,72 +1573,65 @@ CreatePlayerInfoMenu(client, id, track) { menu = CreateMenu(MenuHandler_RankedB5WR); } - + new style = g_wrStyleMode[client]; SetMenuExitButton(menu, true); - for (new i = 0; i < GetArraySize(g_hCache[style][track]); i++) + new nCache[RecordCache]; + GetArrayArray(g_hCache[style][track], index, nCache[0]); + + decl String:sStyle[5]; + IntToString(style, sStyle, sizeof(sStyle)); + + decl String:text[92]; + + SetMenuTitle(menu, "Record Info [ID: %d]\n \n", nCache[Id]); + + FormatEx(text, sizeof(text), "Date: %s", nCache[Date]); + AddMenuItem(menu, sStyle, text); + + FormatEx(text, sizeof(text), "Player: %s (%s)", nCache[Name], nCache[Auth]); + AddMenuItem(menu, sStyle, text); + + FormatEx(text, sizeof(text), "Rank: #%d [FC: %d]", index+1, nCache[FinishCount]); + AddMenuItem(menu, sStyle, text); + + FormatEx(text, sizeof(text), "Time: %s", nCache[TimeString]); + AddMenuItem(menu, sStyle, text); + + FormatEx(text, sizeof(text), "Speed [Avg: %.2f | Max: %.2f | Fin: %.2f]", nCache[AvgSpeed], nCache[MaxSpeed], nCache[FinishSpeed]); + AddMenuItem(menu, sStyle, text); + + if (g_Settings[JumpsEnable]) { - new nCache[RecordCache]; - GetArrayArray(g_hCache[style][track], i, nCache[0]); - - if (nCache[Id] == id) - { - decl String:sStyle[5]; - IntToString(style, sStyle, sizeof(sStyle)); - - decl String:text[92]; - - SetMenuTitle(menu, "Record Info [ID: %d]\n \n", id); - - FormatEx(text, sizeof(text), "Date: %s", nCache[Date]); - AddMenuItem(menu, sStyle, text); - - FormatEx(text, sizeof(text), "Player: %s (%s)", nCache[Name], nCache[Auth]); - AddMenuItem(menu, sStyle, text); - - FormatEx(text, sizeof(text), "Rank: #%d (#%d) [FC: %d]", i+1, nCache[CurrentRank], nCache[FinishCount]); - AddMenuItem(menu, sStyle, text); - - FormatEx(text, sizeof(text), "Time: %s", nCache[TimeString]); - AddMenuItem(menu, sStyle, text); - - FormatEx(text, sizeof(text), "Speed [Avg: %.2f | Max: %.2f | Fin: %.2f]", nCache[AvgSpeed], nCache[MaxSpeed], nCache[FinishSpeed]); - AddMenuItem(menu, sStyle, text); - - if (g_Settings[JumpsEnable]) - { - FormatEx(text, sizeof(text), "Jumps: %d", nCache[Jumps]); - Format(text, sizeof(text), "%s [%.2f ⁰⁄₀]", text, nCache[JumpAcc]); - AddMenuItem(menu, sStyle, text); - } - - if (g_Settings[StrafesEnable]) - { - FormatEx(text, sizeof(text), "Strafes: %d", nCache[Strafes]); - Format(text, sizeof(text), "%s [%.2f ⁰⁄₀]", text, nCache[StrafeAcc]); - AddMenuItem(menu, sStyle, text); - } - - if (g_Settings[MultimodeEnable]) - { - FormatEx(text, sizeof(text), "%Style: %s", g_Physics[style][StyleName]); - AddMenuItem(menu, sStyle, text); - } - break; - } + FormatEx(text, sizeof(text), "Jumps: %d", nCache[Jumps]); + Format(text, sizeof(text), "%s [%.2f ⁰⁄₀]", text, nCache[JumpAcc]); + AddMenuItem(menu, sStyle, text); } - DisplayMenu(menu, client, MENU_TIME_FOREVER); + if (g_Settings[StrafesEnable]) + { + FormatEx(text, sizeof(text), "Strafes: %d", nCache[Strafes]); + Format(text, sizeof(text), "%s [%.2f ⁰⁄₀]", text, nCache[StrafeAcc]); + AddMenuItem(menu, sStyle, text); + } + + if (g_Settings[MultimodeEnable]) + { + FormatEx(text, sizeof(text), "%Style: %s", g_Physics[style][StyleName]); + AddMenuItem(menu, sStyle, text); + } + + DisplayMenu(menu, client, MENU_TIME_FOREVER); } CreateDeleteMenu(client, target, String:targetmap[64], ignored = -1) -{ +{ decl String:buffer[128]; - if(ignored != -1) + if(ignored != -1) FormatEx(buffer, sizeof(buffer), " AND NOT id = '%d'", ignored); - + if (g_hSQL == INVALID_HANDLE) { ConnectSQL(false); @@ -1647,28 +1640,28 @@ CreateDeleteMenu(client, target, String:targetmap[64], ignored = -1) { decl String:auth[32]; GetClientAuthString(target, auth, sizeof(auth)); - + decl String:query[512]; - FormatEx(query, sizeof(query), "SELECT id, time, jumps, style, auth FROM `round` WHERE map = '%s' AND auth = '%s'%s ORDER BY style, time, jumps", targetmap, auth, buffer); - + FormatEx(query, sizeof(query), "SELECT id, time, jumps, style, auth FROM `round` WHERE map = '%s' AND auth = '%s'%s ORDER BY style, time, jumps", targetmap, auth, buffer); + g_deleteMenuSelection[client] = target; SQL_TQuery(g_hSQL, CreateDeleteMenuCallback, query, client, DBPrio_Normal); - } + } else { decl String:auth[32]; GetClientAuthString(target, auth, sizeof(auth)); - + decl String:query[512]; - FormatEx(query, sizeof(query), "SELECT id, time, jumps, style, auth FROM `round` WHERE map = '%s' AND auth = '%s'%s ORDER BY style, time, jumps", targetmap, auth, buffer); - + FormatEx(query, sizeof(query), "SELECT id, time, jumps, style, auth FROM `round` WHERE map = '%s' AND auth = '%s'%s ORDER BY style, time, jumps", targetmap, auth, buffer); + g_deleteMenuSelection[client] = target; SQL_TQuery(g_hSQL, CreateDeleteMenuCallback, query, client, DBPrio_Normal); } } public CreateDeleteMenuCallback(Handle:owner, Handle:hndl, const String:error[], any:client) -{ +{ if (hndl == INVALID_HANDLE) { Timer_LogError("SQL Error on CreateDeleteMenu: %s", error); @@ -1679,33 +1672,33 @@ public CreateDeleteMenuCallback(Handle:owner, Handle:hndl, const String:error[], SetMenuTitle(menu, "%T", "Delete Records", client); SetMenuExitButton(menu, true); - + decl String:auth[32]; GetClientAuthString(client, auth, sizeof(auth)); - + while (SQL_FetchRow(hndl)) { decl String:steamid[32]; SQL_FetchString(hndl, 4, steamid, sizeof(steamid)); - + if (!StrEqual(steamid, auth)) { CloseHandle(menu); return; } - + decl String:id[10]; IntToString(SQL_FetchInt(hndl, 0), id, sizeof(id)); decl String:time[16]; Timer_SecondsToTime(SQL_FetchFloat(hndl, 1), time, sizeof(time), 3); - + decl String:value[92]; FormatEx(value, sizeof(value), "%s %s", time, g_Physics[SQL_FetchInt(hndl, 3)][StyleName]); - + if (g_Settings[JumpsEnable]) Format(value, sizeof(value), "%s %T: %d", value, "Jumps", client, SQL_FetchInt(hndl, 2)); - + AddMenuItem(menu, id, value); } @@ -1714,22 +1707,22 @@ public CreateDeleteMenuCallback(Handle:owner, Handle:hndl, const String:error[], public MenuHandler_DeleteRecord(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { RefreshCache(); CloseHandle(menu); } - else if (action == MenuAction_Select) + else if (action == MenuAction_Select) { - - decl String:info[32]; + + decl String:info[32]; GetMenuItem(menu, itemNum, info, sizeof(info)); - + //fake refresh CreateDeleteMenu(client, g_deleteMenuSelection[client], g_currentMap, StringToInt(info)); - + decl String:query[384]; - FormatEx(query, sizeof(query), "DELETE FROM `round` WHERE id = %s", info); + FormatEx(query, sizeof(query), "DELETE FROM `round` WHERE id = %s", info); SQL_TQuery(g_hSQL, DeleteRecordCallback, query, client, DBPrio_Normal); } @@ -1754,19 +1747,19 @@ public Native_GetStyleRank(Handle:plugin, numParams) new client = GetNativeCell(1); new track = GetNativeCell(2); new style = GetNativeCell(3); - + decl String:auth[32]; GetClientAuthString(client, auth, sizeof(auth)); - + for (new i = 0; i < GetArraySize(g_hCache[style][track]); i++) { new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], i, nCache[0]); - + if (StrEqual(nCache[Auth], auth)) return i+1; } - + return 0; } @@ -1779,11 +1772,11 @@ public Native_GetStyleRecordWRStats(Handle:plugin, numParams) { new style = GetNativeCell(1); new track = GetNativeCell(2); - + SetNativeCellRef(3, g_cachestats[style][track][RecordStatsID]); SetNativeCellRef(4, g_cachestats[style][track][RecordStatsBestTime]); SetNativeCellRef(5, g_cachestats[style][track][RecordStatsCount]); - + return true; } @@ -1792,18 +1785,18 @@ public Native_GetBestRound(Handle:plugin, numParams) new client = GetNativeCell(1); new style = GetNativeCell(2); new track = GetNativeCell(3); - + decl String:auth[32]; GetClientAuthString(client, auth, sizeof(auth)); - + if(GetArraySize(g_hCache[style][track]) <= 0) return false; - + for (new i = 0; i < GetArraySize(g_hCache[style][track]); i++) { new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], i, nCache[0]); - + if (StrEqual(nCache[Auth], auth)) { SetNativeCellRef(4, nCache[Time]); @@ -1811,7 +1804,7 @@ public Native_GetBestRound(Handle:plugin, numParams) return true; } } - + return false; } @@ -1820,50 +1813,50 @@ public Native_GetNewPossibleRank(Handle:plugin, numParams) new style = GetNativeCell(1); new track = GetNativeCell(2); new Float:time = GetNativeCell(3); - + if(time == 0.0) return 0; - + if(GetArraySize(g_hCache[style][track]) <= 0) return 1; - + new i = 0; for (i = 0; i < GetArraySize(g_hCache[style][track]); i++) { new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], i, nCache[0]); - + if (nCache[Time] > time) return i+1; } - + return GetArraySize(g_hCache[style][track])+1; } public Native_GetCacheMapName(Handle:plugin, numParams) { - new nlen = GetNativeCell(2); - + new nlen = GetNativeCell(2); + if (nlen <= 0) return false; - + if (SetNativeString(1, g_currentMap, nlen, true) == SP_ERROR_NONE) return true; - + return false; } public Native_SetCacheMapName(Handle:plugin, numParams) { - new nlen = GetNativeCell(2); + new nlen = GetNativeCell(2); new String:buffer[nlen]; - + GetNativeString(1, buffer, nlen); - + FormatEx(g_currentMap, sizeof(g_currentMap), "%s", buffer); - + RefreshCache(); - + return true; } @@ -1872,16 +1865,16 @@ public Native_GetRankID(Handle:plugin, numParams) new style = GetNativeCell(1); new track = GetNativeCell(2); new rank = GetNativeCell(3); - + if(rank < 1) return false; - + if(GetArraySize(g_hCache[style][track]) < rank) return false; - + new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], rank-1, nCache[0]); - + return nCache[Id]; } @@ -1891,24 +1884,24 @@ public Native_GetRecordHolderName(Handle:plugin, numParams) new track = GetNativeCell(2); new rank = GetNativeCell(3); new nlen = GetNativeCell(5); - + if (nlen <= 0) return false; - + if(rank < 1) return false; - + if(GetArraySize(g_hCache[style][track]) < rank) return false; - + new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], rank-1, nCache[0]); - + decl String:buffer[nlen]; FormatEx(buffer, nlen, "%s", nCache[Name]); if (SetNativeString(4, buffer, nlen, true) == SP_ERROR_NONE) return true; - + return false; } @@ -1918,24 +1911,24 @@ public Native_GetRecordHolderAuth(Handle:plugin, numParams) new track = GetNativeCell(2); new rank = GetNativeCell(3); new nlen = GetNativeCell(5); - + if (nlen <= 0) return false; - + if(rank < 1) return false; - + if(GetArraySize(g_hCache[style][track]) < rank) return false; - + new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], rank-1, nCache[0]); - + decl String:buffer[nlen]; FormatEx(buffer, nlen, "%s", nCache[Auth]); if (SetNativeString(4, buffer, nlen, true) == SP_ERROR_NONE) return true; - + return false; } @@ -1945,24 +1938,24 @@ public Native_GetRecordDate(Handle:plugin, numParams) new track = GetNativeCell(2); new rank = GetNativeCell(3); new nlen = GetNativeCell(5); - + if (nlen <= 0) return false; - + if(rank < 1) return false; - + if(GetArraySize(g_hCache[style][track]) < rank) return false; - + new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], rank-1, nCache[0]); - + decl String:buffer[nlen]; FormatEx(buffer, nlen, "%s", nCache[Date]); if (SetNativeString(4, buffer, nlen, true) == SP_ERROR_NONE) return true; - + return false; } @@ -1971,16 +1964,16 @@ public Native_GetFinishCount(Handle:plugin, numParams) new style = GetNativeCell(1); new track = GetNativeCell(2); new rank = GetNativeCell(3); - + if(rank < 1) return false; - + if(GetArraySize(g_hCache[style][track]) < rank) return false; - + new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], rank-1, nCache[0]); - + return nCache[FinishCount]; } @@ -1990,27 +1983,27 @@ public Native_GetRecordTimeInfo(Handle:plugin, numParams) new track = GetNativeCell(2); new rank = GetNativeCell(3); new nlen = GetNativeCell(6); - + if (nlen <= 0) return false; - + if(rank < 1) return false; - + if(GetArraySize(g_hCache[style][track]) < rank) return false; - + new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], rank-1, nCache[0]); - + SetNativeCellRef(4, nCache[Time]); - + decl String:buffer[nlen]; FormatEx(buffer, nlen, "%s", nCache[TimeString]); - + if (SetNativeString(5, buffer, nlen, true) == SP_ERROR_NONE) return true; - + return false; } @@ -2019,16 +2012,16 @@ public Native_GetRecordSpeedInfo(Handle:plugin, numParams) new style = GetNativeCell(1); new track = GetNativeCell(2); new rank = GetNativeCell(3); - + if(rank < 1) return false; - + if(GetArraySize(g_hCache[style][track]) < rank) return false; - + new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], rank-1, nCache[0]); - + SetNativeCellRef(4, nCache[AvgSpeed]); SetNativeCellRef(5, nCache[MaxSpeed]); SetNativeCellRef(6, nCache[FinishSpeed]); @@ -2041,16 +2034,16 @@ public Native_GetRecordStrafeJumpInfo(Handle:plugin, numParams) new style = GetNativeCell(1); new track = GetNativeCell(2); new rank = GetNativeCell(3); - + if(rank < 1) return false; - + if(GetArraySize(g_hCache[style][track]) < rank) return false; - + new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], rank-1, nCache[0]); - + SetNativeCellRef(4, nCache[Strafes]); SetNativeCellRef(5, nCache[StrafeAcc]); SetNativeCellRef(6, nCache[Jumps]); @@ -2064,25 +2057,25 @@ public Native_GetReplayFileName(Handle:plugin, numParams) new style = GetNativeCell(1); new track = GetNativeCell(2); new rank = GetNativeCell(3); - new nlen = GetNativeCell(5); - + new nlen = GetNativeCell(5); + if (nlen <= 0) return false; - + if(rank < 1) return false; - + if(GetArraySize(g_hCache[style][track]) < rank) return false; - + new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], rank-1, nCache[0]); - + decl String:buffer[nlen]; FormatEx(buffer, nlen, "%s", nCache[ReplayFile]); if (SetNativeString(4, buffer, nlen, true) == SP_ERROR_NONE) return true; - + return false; } @@ -2091,32 +2084,32 @@ public Native_GetReplayPath(Handle:plugin, numParams) new style = GetNativeCell(1); new track = GetNativeCell(2); new rank = GetNativeCell(3); - new nlen = GetNativeCell(5); - + new nlen = GetNativeCell(5); + if (nlen <= 0) return false; - + if(rank < 1) return false; - + if(GetArraySize(g_hCache[style][track]) < rank) return false; - + new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], rank-1, nCache[0]); - + if(nCache[Time] <= 0.0) return false; - + decl String:path[256]; Format(path, sizeof(path), "addons/sourcemod/data/botmimic/%d_%d/%s/%s/%s.rec", style, track, g_currentMap, nCache[Auth], nCache[ReplayFile]); ReplaceString(path, sizeof(path), ":", "_", true); - + decl String:buffer[nlen]; FormatEx(buffer, nlen, "%s", path); if (SetNativeString(4, buffer, nlen, true) == SP_ERROR_NONE) return true; - + return false; } @@ -2127,24 +2120,24 @@ public Native_GetCustom1(Handle:plugin, numParams) new track = GetNativeCell(2); new rank = GetNativeCell(3); new nlen = GetNativeCell(5); - + if (nlen <= 0) return false; - + if(rank < 1) return false; - + if(GetArraySize(g_hCache[style][track]) < rank) return false; - + new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], rank-1, nCache[0]); - + decl String:buffer[nlen]; FormatEx(buffer, nlen, "%s", nCache[Custom1]); if (SetNativeString(4, buffer, nlen, true) == SP_ERROR_NONE) return true; - + return false; } @@ -2154,24 +2147,24 @@ public Native_GetCustom2(Handle:plugin, numParams) new track = GetNativeCell(2); new rank = GetNativeCell(3); new nlen = GetNativeCell(5); - + if (nlen <= 0) return false; - + if(rank < 1) return false; - + if(GetArraySize(g_hCache[style][track]) < rank) return false; - + new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], rank-1, nCache[0]); - + decl String:buffer[nlen]; FormatEx(buffer, nlen, "%s", nCache[Custom2]); if (SetNativeString(4, buffer, nlen, true) == SP_ERROR_NONE) return true; - + return false; } @@ -2182,31 +2175,31 @@ public Native_GetCustom3(Handle:plugin, numParams) new track = GetNativeCell(2); new rank = GetNativeCell(3); new nlen = GetNativeCell(5); - + if (nlen <= 0) return false; - + if(rank < 1) return false; - + if(GetArraySize(g_hCache[style][track]) < rank) return false; - + new nCache[RecordCache]; GetArrayArray(g_hCache[style][track], rank-1, nCache[0]); - + decl String:buffer[nlen]; FormatEx(buffer, nlen, "%s", nCache[Custom3]); if (SetNativeString(4, buffer, nlen, true) == SP_ERROR_NONE) return true; - + return false; } CacheReset() { nCacheTemplate[Ignored] = false; //Just to get rid of a warning, it's just a template - + // Init world record cache for (new style = 0; style < MAX_STYLES; style++) { @@ -2215,7 +2208,7 @@ CacheReset() if(g_hCache[style][track] != INVALID_HANDLE) ClearArray(g_hCache[style][track]); else g_hCache[style][track] = CreateArray(sizeof(nCacheTemplate)); - + g_cacheLoaded[style][track] = false; } } @@ -2226,6 +2219,113 @@ CacheResetSingle(track, style) if(g_hCache[style][track] != INVALID_HANDLE) ClearArray(g_hCache[style][track]); else g_hCache[style][track] = CreateArray(sizeof(nCacheTemplate)); - + g_cacheLoaded[style][track] = false; } + +/* Bypass refresh cache on new record */ + +public OnTimerRecord(client, track, style, Float:time, Float:lasttime, currentrank, newrank) +{ + if(!Timer_IsStyleRanked(style)) + return; + + if(newrank <= 0) + return; + + decl String:buffer[16]; + new Float:wrtime; + Timer_GetRecordTimeInfo(style, track, 1, wrtime, buffer, 16); + + new bool:NewPersonalRecord = false; + new bool:NewWorldRecord = false; + new bool:FirstRecord = false; + + if(currentrank <= 0) + FirstRecord = true; + if(wrtime == 0.0 || time < wrtime) + NewWorldRecord = true; + if(lasttime == 0.0 || time < lasttime) + NewPersonalRecord = true; + + // Nothing improved? + if(!FirstRecord && !NewWorldRecord && !NewPersonalRecord) + { + // Just increase finishcount + new nOldCache[RecordCache]; + GetArrayArray(g_hCache[style][track], currentrank-1, nOldCache[0]); + nOldCache[FinishCount]++; + SetArrayArray(g_hCache[style][track], currentrank-1, nOldCache[0]); + } + else + { + // Build cache entry + new nNewCache[RecordCache]; + new fpsmax; + new bool:enabled; + nNewCache[Ignored] = false; + Timer_GetClientTimer(client, enabled, time, nNewCache[Jumps], fpsmax); + nNewCache[Id] = -1; // Unknown/Fresh + GetClientAuthString(client, nNewCache[Auth], 32); + nNewCache[Time] = time; + Timer_SecondsToTime(time, nNewCache[TimeString], 16, 2); + nNewCache[Style] = style; + GetClientName(client, nNewCache[Name], 32); + FormatTime(nNewCache[Date], 32, "%X", GetTime()); + + // Determine finishcount + if(FirstRecord) + { + nNewCache[FinishCount] = 1; + } + else + { + // Get old record for finishcount + for (new i = 0; i < GetArraySize(g_hCache[style][track]); i++) + { + new nCache[RecordCache]; + GetArrayArray(g_hCache[style][track], i, nCache[0]); + + if (StrEqual(nCache[Auth], nNewCache[Auth])) + { + nNewCache[FinishCount] = nCache[FinishCount]+1; + } + } + } + + // Continue + nNewCache[CurrentRank] = newrank; + Timer_GetJumpAccuracy(client, nNewCache[JumpAcc]); + Timer_GetCurrentSpeed(client, nNewCache[FinishSpeed]); + Timer_GetMaxSpeed(client, nNewCache[MaxSpeed]); + Timer_GetAvgSpeed(client, nNewCache[AvgSpeed]); + + if(g_timerStrafes) + { + nNewCache[Strafes] = Timer_GetStrafeCount(client); + nNewCache[StrafeAcc] = 100.0-(100.0*(float(Timer_GetBoostedStrafeCount(client))/float(Timer_GetStrafeCount(client)))); + } + + // He has already a record? Remove it + if(currentrank > 0) + RemoveFromArray(g_hCache[style][track], currentrank-1); + + // New worldrecord with existing records + if(newrank == 1 && GetArraySize(g_hCache[style][track]) > 0) + { + ShiftArrayUp(g_hCache[style][track], newrank-1); + SetArrayArray(g_hCache[style][track], newrank-1, nNewCache[0]); + } + // Not last rank, so shift and set + else if(newrank <= GetArraySize(g_hCache[style][track])) + { + ShiftArrayUp(g_hCache[style][track], newrank-1); + SetArrayArray(g_hCache[style][track], newrank-1, nNewCache[0]); + } + // First reord on this track or last place + else PushArrayArray(g_hCache[style][track], nNewCache[0]); + + if(newrank == 1) + CollectBestCache(track, style); + } +} diff --git a/gameserver/addons/sourcemod/scripting/timer-worldrecord_latest.sp b/gameserver/addons/sourcemod/scripting/timer-worldrecord_latest.sp index 5485d47..c733074 100644 --- a/gameserver/addons/sourcemod/scripting/timer-worldrecord_latest.sp +++ b/gameserver/addons/sourcemod/scripting/timer-worldrecord_latest.sp @@ -30,7 +30,7 @@ new Handle:g_hSQL = INVALID_HANDLE; new g_latestRecords[3][LATEST_LIMIT][Record]; new g_RecordCount[3]; -public Plugin:myinfo = +public Plugin:myinfo = { name = "[Timer] Worldrecord - Latest WRs", author = "Zipcore", @@ -44,12 +44,12 @@ public OnPluginStart() RegConsoleCmd("sm_latest", Cmd_LatestChoose); RegConsoleCmd("sm_rr", Cmd_LatestChoose); RegConsoleCmd("sm_recent", Cmd_LatestChoose); - + if (g_hSQL == INVALID_HANDLE) { ConnectSQL(); } - + LoadPhysics(); LoadTimerSettings(); } @@ -61,7 +61,7 @@ public OnMapStart() ConnectSQL(); } else LoadLatestRecords(); - + LoadPhysics(); LoadTimerSettings(); } @@ -82,7 +82,7 @@ public OnTimerSqlStop() ConnectSQL() { g_hSQL = Handle:Timer_SqlGetConnection(); - + if (g_hSQL == INVALID_HANDLE) CreateTimer(0.1, Timer_SQLReconnect, _ , TIMER_FLAG_NO_MAPCHANGE); else LoadLatestRecords(); @@ -102,13 +102,13 @@ public OnTimerRecord(client, track, mode, Float:time, Float:lasttime, currentran LoadLatestRecords() { decl String:sQuery[1024]; - + FormatEx(sQuery, sizeof(sQuery), "SELECT `map`, `track`, `style`, `auth`, `name`, `time`, `rank`, `date` FROM `round` ORDER BY `date` DESC LIMIT %d", LATEST_LIMIT); SQL_TQuery(g_hSQL, LoadLatestRecordsCallback, sQuery, RECORD_ANY, DBPrio_Low); - + FormatEx(sQuery, sizeof(sQuery), "SELECT `map`, `track`, `style`, `auth`, `name`, `time`, `rank`, `date` FROM `round` WHERE `rank` <= 10 ORDER BY `date` DESC LIMIT %d", LATEST_LIMIT); SQL_TQuery(g_hSQL, LoadLatestRecordsCallback, sQuery, RECORD_TOP, DBPrio_Low); - + FormatEx(sQuery, sizeof(sQuery), "SELECT `map`, `track`, `style`, `auth`, `name`, `time`, `rank`, `date` FROM `round` WHERE `rank` = 1 ORDER BY `date` DESC LIMIT %d", LATEST_LIMIT); SQL_TQuery(g_hSQL, LoadLatestRecordsCallback, sQuery, RECORD_WORLD, DBPrio_Low); } @@ -132,14 +132,14 @@ public LoadLatestRecordsCallback(Handle:owner, Handle:hndl, const String:error[] g_latestRecords[recordtype][recordCounter][RecordTime] = SQL_FetchFloat(hndl, 5); g_latestRecords[recordtype][recordCounter][RecordRank] = SQL_FetchInt(hndl, 6); SQL_FetchString(hndl, 7, g_latestRecords[recordtype][recordCounter][RecordDate], 32); - + recordCounter++; if (recordCounter == LATEST_LIMIT) { break; } } - + g_RecordCount[recordtype] = recordCounter; } @@ -148,13 +148,13 @@ public Action:Cmd_LatestChoose(client, args) if (client) { new Handle:menu = CreateMenu(Handle_LatestChoose); - + SetMenuTitle(menu, "Select filter for latest records"); - + AddMenuItem(menu, "any", "Any"); AddMenuItem(menu, "top", "Top10"); AddMenuItem(menu, "world", "World"); - + DisplayMenu(menu, client, MENU_TIME_FOREVER); } @@ -192,7 +192,7 @@ public Handle_LatestChoose(Handle:menu, MenuAction:action, client, itemNum) Menu_Latest(client, type) { new Handle:menu = INVALID_HANDLE; - + if(type == RECORD_TOP) { menu = CreateMenu(Handle_LatestTop); @@ -218,24 +218,24 @@ Menu_Latest(client, type) decl String:buffer[512]; Format(buffer, sizeof(buffer), "[#%d] %s", i+1, sTime); - - if(g_latestRecords[type][i][RecordTrack] == TRACK_BONUS) - Format(buffer, sizeof(buffer), "%s [B]", buffer); - + + if(g_latestRecords[type][i][RecordTrack] >= TRACK_BONUS) + Format(buffer, sizeof(buffer), "%s [B%d]", buffer, g_latestRecords[type][i][RecordTrack]); + Format(buffer, sizeof(buffer), "%s - %s", buffer, g_latestRecords[type][i][RecordName]); - + decl String:sInfo[3]; Format(sInfo, sizeof(sInfo), "%d", i); AddMenuItem(menu, sInfo, buffer); } - + if (g_RecordCount[type] == 0) { decl String:buffer[512]; Format(buffer, sizeof(buffer), "No records available!"); AddMenuItem(menu, "", buffer, ITEMDRAW_DISABLED); } - + SetMenuExitButton(menu, true); DisplayMenu(menu, client, 20); } @@ -251,32 +251,32 @@ public Handle_Latest(Handle:menu, MenuAction:action, client, itemNum) if(found) { new Handle:menu2 = CreateMenu(Handle_LatestChoose); - + SetMenuTitle(menu2, "Details"); - + new String:buffer[512]; - + Format(buffer, sizeof(buffer), "Map: %s", g_latestRecords[RECORD_ANY][id][RecordMap]); - if(g_latestRecords[RECORD_ANY][id][RecordTrack] == TRACK_BONUS) Format(buffer, sizeof(buffer), "%s [Bonus]", buffer); + if(g_latestRecords[RECORD_WORLD][id][RecordTrack] >= TRACK_BONUS) Format(buffer, sizeof(buffer), "%s [Bonus%d]", buffer, g_latestRecords[RECORD_WORLD][id][RecordTrack]); AddMenuItem(menu2, "any", buffer); - + if(g_Settings[MultimodeEnable]) { Format(buffer, sizeof(buffer), "Style: %s", g_Physics[g_latestRecords[RECORD_ANY][id][RecordStyle]][StyleName]); AddMenuItem(menu2, "any", buffer); } - + Format(buffer, sizeof(buffer), "Name: %s [%s]", g_latestRecords[RECORD_ANY][id][RecordName], g_latestRecords[RECORD_ANY][id][RecordAuth]); AddMenuItem(menu2, "any", buffer); - + decl String:sTime[128]; Timer_SecondsToTime(g_latestRecords[RECORD_ANY][id][RecordTime], sTime, sizeof(sTime), 2); Format(buffer, sizeof(buffer), "Time: %s (#%d)", sTime, g_latestRecords[RECORD_ANY][id][RecordRank]); AddMenuItem(menu2, "any", buffer); - + Format(buffer, sizeof(buffer), "Date: %s", g_latestRecords[RECORD_ANY][id][RecordDate]); AddMenuItem(menu2, "any", buffer); - + DisplayMenu(menu2, client, MENU_TIME_FOREVER); } } @@ -292,32 +292,32 @@ public Handle_LatestTop(Handle:menu, MenuAction:action, client, itemNum) if(found) { new Handle:menu2 = CreateMenu(Handle_LatestChoose); - + SetMenuTitle(menu2, "Details"); - + new String:buffer[512]; - + Format(buffer, sizeof(buffer), "Map: %s", g_latestRecords[RECORD_TOP][id][RecordMap]); - if(g_latestRecords[RECORD_TOP][id][RecordTrack] == TRACK_BONUS) Format(buffer, sizeof(buffer), "%s [Bonus]", buffer); + if(g_latestRecords[RECORD_WORLD][id][RecordTrack] >= TRACK_BONUS) Format(buffer, sizeof(buffer), "%s [Bonus%d]", buffer, g_latestRecords[RECORD_WORLD][id][RecordTrack]); AddMenuItem(menu2, "top", buffer); - + if(g_Settings[MultimodeEnable]) { Format(buffer, sizeof(buffer), "Style: %s", g_Physics[g_latestRecords[RECORD_TOP][id][RecordStyle]][StyleName]); AddMenuItem(menu2, "top", buffer); } - + Format(buffer, sizeof(buffer), "Name: %s [%s]", g_latestRecords[RECORD_TOP][id][RecordName], g_latestRecords[RECORD_TOP][id][RecordAuth]); AddMenuItem(menu2, "top", buffer); - + decl String:sTime[128]; Timer_SecondsToTime(g_latestRecords[RECORD_TOP][id][RecordTime], sTime, sizeof(sTime), 2); Format(buffer, sizeof(buffer), "Time: %s (#%d)", sTime, g_latestRecords[RECORD_TOP][id][RecordRank]); AddMenuItem(menu2, "top", buffer); - + Format(buffer, sizeof(buffer), "Date: %s", g_latestRecords[RECORD_TOP][id][RecordDate]); AddMenuItem(menu2, "top", buffer); - + DisplayMenu(menu2, client, MENU_TIME_FOREVER); } } @@ -333,32 +333,32 @@ public Handle_LatestWorld(Handle:menu, MenuAction:action, client, itemNum) if(found) { new Handle:menu2 = CreateMenu(Handle_LatestChoose); - + SetMenuTitle(menu2, "Details"); - + new String:buffer[512]; - + Format(buffer, sizeof(buffer), "Map: %s", g_latestRecords[RECORD_WORLD][id][RecordMap]); - if(g_latestRecords[RECORD_WORLD][id][RecordTrack] == TRACK_BONUS) Format(buffer, sizeof(buffer), "%s [Bonus]", buffer); + if(g_latestRecords[RECORD_WORLD][id][RecordTrack] >= TRACK_BONUS) Format(buffer, sizeof(buffer), "%s [Bonus%d]", buffer, g_latestRecords[RECORD_WORLD][id][RecordTrack]); AddMenuItem(menu2, "world", buffer); - + if(g_Settings[MultimodeEnable]) { Format(buffer, sizeof(buffer), "Style: %s", g_Physics[g_latestRecords[RECORD_WORLD][id][RecordStyle]][StyleName]); AddMenuItem(menu2, "world", buffer); } - + Format(buffer, sizeof(buffer), "Name: %s [%s]", g_latestRecords[RECORD_WORLD][id][RecordName], g_latestRecords[RECORD_WORLD][id][RecordAuth]); AddMenuItem(menu2, "world", buffer); - + decl String:sTime[128]; Timer_SecondsToTime(g_latestRecords[RECORD_ANY][id][RecordTime], sTime, sizeof(sTime), 2); Format(buffer, sizeof(buffer), "Time: %s", sTime, g_latestRecords[RECORD_WORLD][id][RecordRank]); AddMenuItem(menu2, "world", buffer); - + Format(buffer, sizeof(buffer), "Date: %s", g_latestRecords[RECORD_WORLD][id][RecordDate]); AddMenuItem(menu2, "world", buffer); - + DisplayMenu(menu2, client, MENU_TIME_FOREVER); } } diff --git a/gameserver/addons/sourcemod/scripting/timer-worldrecord_maptop.sp b/gameserver/addons/sourcemod/scripting/timer-worldrecord_maptop.sp index e478fb7..edfa23e 100644 --- a/gameserver/addons/sourcemod/scripting/timer-worldrecord_maptop.sp +++ b/gameserver/addons/sourcemod/scripting/timer-worldrecord_maptop.sp @@ -9,7 +9,7 @@ #define MAPTOP_LIMIT 100 -public Plugin:myinfo = +public Plugin:myinfo = { name = "[Timer] Worldrecord - MapTop", author = "Zipcore, Credits: Das D", @@ -28,11 +28,10 @@ public OnPluginStart() { RegConsoleCmd("sm_mtop", Cmd_MapTop_Record, "Displays Top of a given map"); RegConsoleCmd("sm_mbtop", Cmd_MapBonusTop_Record, "Displays BonusTop of a given map"); - RegConsoleCmd("sm_mstop", Cmd_MapShortTop_Record, "Displays ShortTop of a given map"); LoadPhysics(); LoadTimerSettings(); - + if (g_hSQL == INVALID_HANDLE) { ConnectSQL(); @@ -43,7 +42,7 @@ public OnMapStart() { LoadPhysics(); LoadTimerSettings(); - + if (g_hSQL == INVALID_HANDLE) { ConnectSQL(); @@ -66,7 +65,7 @@ public OnTimerSqlStop() ConnectSQL() { g_hSQL = Handle:Timer_SqlGetConnection(); - + if (g_hSQL == INVALID_HANDLE) CreateTimer(0.1, Timer_SQLReconnect, _ , TIMER_FLAG_NO_MAPCHANGE); } @@ -91,7 +90,7 @@ public Action:Cmd_MapTop_Record(client, args) { decl String:sMapName[64]; GetCmdArg(1, sMapName, sizeof(sMapName)); - + if(g_Settings[MultimodeEnable]) TopStylePanel(client, sMapName); else SQL_TopPanel(client, sMapName, g_StyleDefault, TRACK_NORMAL); } @@ -101,8 +100,8 @@ public Action:Cmd_MapTop_Record(client, args) GetCmdArg(1, sMapName, sizeof(sMapName)); decl String:sStyle[64]; GetCmdArg(2, sStyle, sizeof(sStyle)); - - for(new i = 0; i < MAX_STYLES-1; i++) + + for(new i = 0; i < MAX_STYLES-1; i++) { if(!g_Physics[i][StyleEnable]) continue; @@ -110,7 +109,7 @@ public Action:Cmd_MapTop_Record(client, args) continue; if(StrEqual(g_Physics[i][StyleQuickCommand], "")) continue; - + if(StrEqual(g_Physics[i][StyleQuickCommand], sStyle)) { SQL_TopPanel(client, sMapName, i, TRACK_NORMAL); @@ -118,7 +117,7 @@ public Action:Cmd_MapTop_Record(client, args) } } } - + return Plugin_Handled; } @@ -129,21 +128,21 @@ TopStylePanel(client, String:sMapName[64]) new Handle:menu = CreateMenu(MenuHandler_TopStylePanel); SetMenuTitle(menu, "Select Style", client); - + SetMenuExitButton(menu, true); - for(new i = 0; i < MAX_STYLES-1; i++) + for(new i = 0; i < MAX_STYLES-1; i++) { if(!g_Physics[i][StyleEnable]) continue; if(g_Physics[i][StyleCategory] != MCategory_Ranked) continue; - + new String:buffer[8]; IntToString(i, buffer, sizeof(buffer)); - + AddMenuItem(menu, buffer, g_Physics[i][StyleName]); - } + } Format(g_SelectedMap[client], 64, sMapName); DisplayMenu(menu, client, MENU_TIME_FOREVER); @@ -152,15 +151,15 @@ TopStylePanel(client, String:sMapName[64]) public MenuHandler_TopStylePanel(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Select) + else if (action == MenuAction_Select) { - decl String:info[8]; + decl String:info[8]; GetMenuItem(menu, itemNum, info, sizeof(info)); - + SQL_TopPanel(client, g_SelectedMap[client], StringToInt(info), TRACK_NORMAL); } } @@ -179,7 +178,7 @@ public Action:Cmd_MapBonusTop_Record(client, args) { decl String:sMapName[64]; GetCmdArg(1, sMapName, sizeof(sMapName)); - + if(g_Settings[MultimodeEnable]) BonusTopStylePanel(client, sMapName); else SQL_TopPanel(client, sMapName, g_StyleDefault, TRACK_BONUS); } @@ -189,8 +188,8 @@ public Action:Cmd_MapBonusTop_Record(client, args) GetCmdArg(1, sMapName, sizeof(sMapName)); decl String:sStyle[64]; GetCmdArg(2, sStyle, sizeof(sStyle)); - - for(new i = 0; i < MAX_STYLES-1; i++) + + for(new i = 0; i < MAX_STYLES-1; i++) { if(!g_Physics[i][StyleEnable]) continue; @@ -198,7 +197,7 @@ public Action:Cmd_MapBonusTop_Record(client, args) continue; if(StrEqual(g_Physics[i][StyleQuickCommand], "")) continue; - + if(StrEqual(g_Physics[i][StyleQuickCommand], sStyle)) { SQL_TopPanel(client, sMapName, i, TRACK_BONUS); @@ -206,7 +205,7 @@ public Action:Cmd_MapBonusTop_Record(client, args) } } } - + return Plugin_Handled; } @@ -217,21 +216,21 @@ BonusTopStylePanel(client, String:sMapName[64]) new Handle:menu = CreateMenu(MenuHandler_BonusTopStylePanel); SetMenuTitle(menu, "Select Style", client); - + SetMenuExitButton(menu, true); - for(new i = 0; i < MAX_STYLES-1; i++) + for(new i = 0; i < MAX_STYLES-1; i++) { if(!g_Physics[i][StyleEnable]) continue; if(g_Physics[i][StyleCategory] != MCategory_Ranked) continue; - + new String:buffer[8]; IntToString(i, buffer, sizeof(buffer)); - + AddMenuItem(menu, buffer, g_Physics[i][StyleName]); - } + } Format(g_SelectedMap[client], 64, sMapName); DisplayMenu(menu, client, MENU_TIME_FOREVER); @@ -240,126 +239,38 @@ BonusTopStylePanel(client, String:sMapName[64]) public MenuHandler_BonusTopStylePanel(Handle:menu, MenuAction:action, client, itemNum) { - if (action == MenuAction_End) + if (action == MenuAction_End) { CloseHandle(menu); } - else if (action == MenuAction_Select) + else if (action == MenuAction_Select) { - decl String:info[8]; + decl String:info[8]; GetMenuItem(menu, itemNum, info, sizeof(info)); - - SQL_TopPanel(client, g_SelectedMap[client], StringToInt(info), TRACK_BONUS); - } -} - -/* Map Top Short */ - -public Action:Cmd_MapShortTop_Record(client, args) -{ - if(args < 1) - { - if(g_Settings[MultimodeEnable]) ReplyToCommand(client, "[SM] Usage: sm_sbtop