diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib.inc index 7aeb64ce..2d6413a6 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib.inc @@ -21,6 +21,8 @@ #include #include #include +#include +//#include #include #include #include diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/arrays.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/arrays.inc index 8faaa4eb..1c9863e6 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/arrays.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/arrays.inc @@ -27,7 +27,7 @@ stock Array_FindValue(any:array[], size, any:value, start=0) return i; } } - + return -1; } @@ -53,7 +53,7 @@ stock Array_FindString(const String:array[][], size, const String:str[], bool:ca return i; } } - + return -1; } @@ -74,18 +74,18 @@ stock Array_FindLowestValue(any:array[], size, start=0) new any:value = array[start]; new any:tempValue; new x = start; - + for (new i=start; i < size; i++) { - + tempValue = array[i]; - + if (tempValue < value) { value = tempValue; x = i; } - + } - + return x; } @@ -106,18 +106,18 @@ stock Array_FindHighestValue(any:array[], size, start=0) new any:value = array[start]; new any:tempValue; new x = start; - + for (new i=start; i < size; i++) { - + tempValue = array[i]; - + if (tempValue > value) { value = tempValue; x = i; } - + } - + return x; } diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/clients.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/clients.inc index 45a8c901..0fca2bcb 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/clients.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/clients.inc @@ -45,6 +45,15 @@ */ #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. * @@ -100,7 +109,7 @@ stock bool:Client_IsValid(client, bool:checkConnected=true) if (checkConnected && !IsClientConnected(client)) { return false; } - + return true; } @@ -149,14 +158,14 @@ stock Client_FindBySteamId(const String:auth[]) if (!IsClientAuthorized(client)) { continue; } - - GetClientAuthString(client, clientAuth, sizeof(clientAuth)); + + GetClientAuthId(client, AuthId_Steam2, clientAuth, sizeof(clientAuth)); if (StrEqual(auth, clientAuth)) { return client; } } - + return -1; } @@ -171,12 +180,12 @@ 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; } - + GetClientName(client, clientName, sizeof(clientName)); if (partOfName) { @@ -188,7 +197,7 @@ stock Client_FindByName(const String:name[], bool:partOfName=true, bool:caseSens return client; } } - + return -1; } @@ -218,7 +227,7 @@ enum Obs_Allow /** * Gets the client's observer mode (Obs_Mode). - * + * * @param client Client Index. * @return The current observer mode (ObsMode). */ @@ -232,7 +241,7 @@ stock Obs_Mode:Client_GetObserverMode(client) * Sets the client's observer mode. * Use a value of the Obs_Mode enum. * This is a rewrite of CBasePlayer::SetObserverMode(). - * + * * @param client Client Index. * @param mode New Observer mode value (Obs_Mode). * @param updateMoveType Set to true (default) to allow this function updating the movetype, false otherwise. @@ -243,7 +252,7 @@ stock bool:Client_SetObserverMode(client, Obs_Mode:mode, bool:updateMoveType=tru if (mode < OBS_MODE_NONE || mode >= NUM_OBSERVER_MODES) { return false; } - + // check mp_forcecamera settings for dead players if (mode > OBS_MODE_FIXED && GetClientTeam(client) > TEAM_SPECTATOR) { @@ -273,7 +282,7 @@ stock bool:Client_SetObserverMode(client, Obs_Mode:mode, bool:updateMoveType=tru switch (mode) { case OBS_MODE_NONE, OBS_MODE_FIXED, OBS_MODE_DEATHCAM: { Client_SetFOV(client, 0); // Reset FOV - + if (updateMoveType) { SetEntityMoveType(client, MOVETYPE_NONE); } @@ -281,7 +290,7 @@ stock bool:Client_SetObserverMode(client, Obs_Mode:mode, bool:updateMoveType=tru case OBS_MODE_CHASE, OBS_MODE_IN_EYE: { // udpate FOV and viewmodels Client_SetViewOffset(client, NULL_VECTOR); - + if (updateMoveType) { SetEntityMoveType(client, MOVETYPE_OBSERVER); } @@ -289,7 +298,7 @@ stock bool:Client_SetObserverMode(client, Obs_Mode:mode, bool:updateMoveType=tru case OBS_MODE_ROAMING: { Client_SetFOV(client, 0); // Reset FOV Client_SetViewOffset(client, NULL_VECTOR); - + if (updateMoveType) { SetEntityMoveType(client, MOVETYPE_OBSERVER); } @@ -301,18 +310,18 @@ stock bool:Client_SetObserverMode(client, Obs_Mode:mode, bool:updateMoveType=tru /** * Gets the client's last oberserver mode - * + * * @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"); } /** * Sets the client's last oberserver mode - * + * * @param client Client Index. * @param mode Last Observer mode * @noreturn @@ -325,7 +334,7 @@ stock Client_SetObserverLastMode(client, Obs_Mode:mode) /** * Gets the client's view offset. * This is the position relative to the client itself. - * + * * @param client Client Index. * @param vec Vector Buffer. * @noreturn @@ -338,7 +347,7 @@ stock Client_GetViewOffset(client, Float:vec[3]) /** * Sets the client's view offset. * This is the position relative to the client itself. - * + * * @param client Client Index. * @param vec Vector buffer. * @noreturn @@ -350,7 +359,7 @@ stock Client_SetViewOffset(client, Float:vec[3]) /** * Gets the client's current observer target entity. - * + * * @param client Client Index. * @return Observed Entity Index. */ @@ -361,7 +370,7 @@ stock Client_GetObserverTarget(client) /** * Sets the client's current observer target entity. - * + * * @param client Client Index. * @param entity Observed Entity Index. * @param resetFOV If to reset the client's field of view. @@ -370,7 +379,7 @@ stock Client_GetObserverTarget(client) stock Client_SetObserverTarget(client, entity, bool:resetFOV=true) { SetEntPropEnt(client, Prop_Send, "m_hObserverTarget", entity); - + if (resetFOV) { Client_SetFOV(client, 0); } @@ -378,7 +387,7 @@ stock Client_SetObserverTarget(client, entity, bool:resetFOV=true) /** * Gets the client's Field Of View. - * + * * @param client Client Index. * @return Field Of View */ @@ -389,7 +398,7 @@ stock Client_GetFOV(client) /** * Sets the client's Field Of View. - * + * * @param client Client Index. * @param value Field Of View * @noreturn @@ -401,7 +410,7 @@ stock Client_SetFOV(client, value) /** * Checks if the client's View Model is drawn for the client. - * + * * @param client Client Index. * @return True if the viewmodel is drawn, false otherwise. */ @@ -412,7 +421,7 @@ stock bool:Client_DrawViewModel(client) /** * Sets if to draw the client's view model for the client. - * + * * @param client Client Index. * @param drawViewModel Set to true if to draw, false otherwise. * @noreturn @@ -482,20 +491,36 @@ stock Client_IsInThirdPersonMode(client) stock bool:Client_ScreenFade(client, duration, mode, holdtime=-1, r=0, g=0, b=0, a=255, bool:reliable=true) { new Handle:userMessage = StartMessageOne("Fade", client, (reliable?USERMSG_RELIABLE:0)); - + if (userMessage == INVALID_HANDLE) { 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; } @@ -511,14 +536,14 @@ stock Client_GetClones(client, cloneList[]) { new x=0; decl String:ip_client[16], String:ip_player[16]; - + GetClientIP(client, ip_client, sizeof(client)); - + for (new player=1; player <= MaxClients; player++) { - + if (IsClientInGame(player)) { GetClientIP(player, ip_player, sizeof(ip_player)); - + if (StrEqual(ip_client, ip_player, false)) { cloneList[x++] = player; } @@ -535,18 +560,18 @@ stock Client_GetClones(client, cloneList[]) * @return Returns true if the client is on a ladder other wise false. */ stock bool:Client_IsOnLadder(client) -{ +{ new MoveType:movetype = GetEntityMoveType(client); - + if (movetype == MOVETYPE_LADDER) { return true; } - else{ + else{ return false; } } -enum Water_level +enum Water_Level { WATER_LEVEL_NOT_IN_WATER = 0, WATER_LEVEL_FEET_IN_WATER, @@ -561,7 +586,7 @@ enum Water_level * @return Returns 0 if not in water. 1 if feets are in water. 2 if waist is in water. 3 if head is in water. */ stock Water_Level:Client_GetWaterLevel(client) -{ +{ return Water_Level:GetEntProp(client, Prop_Send, "m_nWaterLevel"); } @@ -578,18 +603,18 @@ stock Float:Client_GetSuitSprintPower(client) /* * Sets a client suit sprint power in percent. - * + * * @param client Client index. * @param power power (0.0 to 100.0) * @noreturn */ stock Client_SetSuitSprintPower(client, Float:power) -{ +{ SetEntPropFloat(client, Prop_Send, "m_flSuitPower", power); } /* - * Returns the client count put in the server. + * Returns the client count put in the server. * * @param inGameOnly If false connecting players are also counted. * @param countBots If true bots will be counted too. @@ -598,21 +623,21 @@ stock Client_SetSuitSprintPower(client, Float:power) stock Client_GetCount(bool:countInGameOnly=true, bool:countFakeClients=true) { new numClients = 0; - + for (new client=1; client <= MaxClients; client++) { - + if (!IsClientConnected(client)) { continue; } - + if (countInGameOnly && !IsClientInGame(client)) { continue; } - + if (!countFakeClients && IsFakeClient(client)) { continue; } - + numClients++; } @@ -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) { @@ -638,8 +663,8 @@ stock Client_GetFakePing(client, bool:goldSource=true) new ping; new Float:latency = GetClientLatency(client, NetFlow_Outgoing); // in seconds - - // that should be the correct latency, we assume that cmdrate is higher + + // that should be the correct latency, we assume that cmdrate is higher // then updaterate, what is the case for default settings decl String:cl_cmdrate[4]; GetClientInfo(client, "cl_cmdrate", cl_cmdrate, sizeof(cl_cmdrate)); @@ -655,7 +680,7 @@ stock Client_GetFakePing(client, bool:goldSource=true) ping = RoundFloat(latency * 1000.0); // as msecs ping = Math_Clamp(ping, 5, 1000); // set bounds, dont show pings under 5 msecs - + return ping; } @@ -684,7 +709,7 @@ stock Client_GetLastPlaceName(client, String:buffer[], size) } /** - * Returns the client's Score. + * Returns the client's Score. * * @param client Client's index. * @return Score. @@ -866,7 +891,7 @@ stock bool:Client_ExitVehicle(client) if (vehicle == -1) { return false; } - + return AcceptEntityInput(vehicle, "ExitVehicle"); } @@ -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; @@ -930,7 +975,7 @@ stock bool:Client_RawAudioToAll(const emitter, const String:soundfile[], Float:l /** * Sets an Impulse value for a client (eg: "impulse 100" for flashlight, value would be 100). * See: http://developer.valvesoftware.com/wiki/Impulse - * + * * @param client Client Index * @param value The impulse command value. * @return True on success, false on failure. @@ -952,9 +997,9 @@ stock Client_GetWeaponsOffset(client) static offset = -1; if (offset == -1) { - offset = FindDataMapOffs(client, "m_hMyWeapons"); + offset = FindDataMapInfo(client, "m_hMyWeapons"); } - + return offset; } @@ -967,11 +1012,11 @@ stock Client_GetWeaponsOffset(client) stock Client_GetActiveWeapon(client) { new weapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon"); - + if (!Entity_IsValid(weapon)) { return INVALID_ENT_REFERENCE; } - + return weapon; } @@ -981,19 +1026,19 @@ stock Client_GetActiveWeapon(client) * @param client Client Index. * @param buffer String Buffer to store the weapon's classname. * @param size Max size of String: buffer. - * @return Weapon Entity Index on success or INVALID_ENT_REFERENCE otherwise + * @return Weapon Entity Index on success or INVALID_ENT_REFERENCE otherwise */ stock Client_GetActiveWeaponName(client, String:buffer[], size) { new weapon = Client_GetActiveWeapon(client); - + if (weapon == INVALID_ENT_REFERENCE) { buffer[0] = '\0'; return INVALID_ENT_REFERENCE; } - + Entity_GetClassName(weapon, buffer, size); - + return weapon; } @@ -1008,7 +1053,7 @@ stock Client_GetActiveWeaponName(client, String:buffer[], size) stock Client_SetActiveWeapon(client, weapon) { SetEntPropEnt(client, Prop_Data, "m_hActiveWeapon", weapon); - ChangeEdictState(client, FindDataMapOffs(client, "m_hActiveWeapon")); + ChangeEdictState(client, FindDataMapInfo(client, "m_hActiveWeapon")); } /** @@ -1022,13 +1067,13 @@ stock Client_SetActiveWeapon(client, weapon) stock bool:Client_ChangeWeapon(client, const String:className[]) { new weapon = Client_GetWeapon(client, className); - + if (weapon == INVALID_ENT_REFERENCE) { return false; } Client_SetActiveWeapon(client,weapon); - + return true; } @@ -1038,27 +1083,27 @@ stock bool:Client_ChangeWeapon(client, const String:className[]) * If the default weapon can't be found, the first weapon in the list is taken. * If the first weapon can't be found, INVALID_ENT_REFERENCEE is returned. * - * @param client Client Index. + * @param client Client Index. * @return Entity Index or, INVALID_ENT_REFERENCE. */ stock Client_ChangeToLastWeapon(client) { new weapon = Client_GetLastActiveWeapon(client); - + if (weapon == INVALID_ENT_REFERENCE) { weapon = Client_GetDefaultWeapon(client); - + if (weapon == INVALID_ENT_REFERENCE) { weapon = Client_GetFirstWeapon(client); - + if (weapon == INVALID_ENT_REFERENCE) { return INVALID_ENT_REFERENCE; } } } - + Client_SetActiveWeapon(client, weapon); - + return weapon; } @@ -1071,11 +1116,11 @@ stock Client_ChangeToLastWeapon(client) stock Client_GetLastActiveWeapon(client) { new weapon = GetEntPropEnt(client, Prop_Data, "m_hLastWeapon"); - + if (!Entity_IsValid(weapon)) { return INVALID_ENT_REFERENCE; } - + return weapon; } @@ -1090,14 +1135,14 @@ stock Client_GetLastActiveWeapon(client) stock bool:Client_GetLastActiveWeaponName(client, String:buffer[], size) { new weapon = Client_GetLastActiveWeapon(client); - + if (weapon == INVALID_ENT_REFERENCE) { buffer[0] = '\0'; return false; } - + Entity_GetClassName(weapon, buffer, size); - + return true; } @@ -1111,7 +1156,7 @@ stock bool:Client_GetLastActiveWeaponName(client, String:buffer[], size) stock Client_SetLastActiveWeapon(client, weapon) { SetEntPropEnt(client, Prop_Data, "m_hLastWeapon", weapon); - ChangeEdictState(client, FindDataMapOffs(client, "m_hLastWeapon")); + ChangeEdictState(client, FindDataMapInfo(client, "m_hLastWeapon")); } /** @@ -1125,7 +1170,7 @@ stock Client_SetLastActiveWeapon(client, weapon) stock Client_EquipWeapon(client, weapon, bool:switchTo=false) { EquipPlayerWeapon(client, weapon); - + if (switchTo) { Client_SetActiveWeapon(client, weapon); } @@ -1135,7 +1180,7 @@ stock Client_EquipWeapon(client, weapon, bool:switchTo=false) * Savly detaches a clients weapon, to remove it as example. * The client will select his last weapon when detached. * - * @param client Client Index. + * @param client Client Index. * @param weapon Entity Index of the weapon, you'd like to detach. * @return True on success, false otherwise. */ @@ -1144,11 +1189,11 @@ stock bool:Client_DetachWeapon(client, weapon) if (!RemovePlayerItem(client, weapon)) { return false; } - + if (Client_GetActiveWeapon(client) == INVALID_ENT_REFERENCE) { Client_ChangeToLastWeapon(client); } - + return true; } @@ -1166,7 +1211,7 @@ stock Client_GiveWeapon(client, const String:className[], bool:switchTo=true) if (weapon == INVALID_ENT_REFERENCE) { weapon = Weapon_CreateForOwner(client, className); - + if (weapon == INVALID_ENT_REFERENCE) { return INVALID_ENT_REFERENCE; } @@ -1192,7 +1237,7 @@ stock Client_GiveWeapon(client, const String:className[], bool:switchTo=true) stock Client_GiveWeaponAndAmmo(client, const String:className[], bool:switchTo=true, primaryAmmo=-1, secondaryAmmo=-1, primaryClip=-1, secondaryClip=-1) { new weapon = Client_GiveWeapon(client, className, switchTo); - + if (weapon == INVALID_ENT_REFERENCE) { return INVALID_ENT_REFERENCE; } @@ -1227,27 +1272,27 @@ stock bool:Client_RemoveWeapon(client, const String:className[], bool:firstOnly= offset += 4; new weapon = GetEntDataEnt2(client, offset); - + if (!Weapon_IsValid(weapon)) { continue; } - + if (!Entity_ClassNameMatches(weapon, className)) { continue; } - + if (clearAmmo) { Client_SetWeaponPlayerAmmoEx(client, weapon, 0, 0); } - + if (Client_GetActiveWeapon(client) == weapon) { Client_ChangeToLastWeapon(client); } - + if (RemovePlayerItem(client, weapon)) { Entity_Kill(weapon); } - + if (firstOnly) { return true; } @@ -1269,22 +1314,22 @@ stock bool:Client_RemoveWeapon(client, const String:className[], bool:firstOnly= stock Client_RemoveAllWeapons(client, const String:exclude[]="", bool:clearAmmo=false) { new offset = Client_GetWeaponsOffset(client) - 4; - + new numWeaponsRemoved = 0; for (new i=0; i < MAX_WEAPONS; i++) { offset += 4; new weapon = GetEntDataEnt2(client, offset); - + if (!Weapon_IsValid(weapon)) { continue; } - + if (exclude[0] != '\0' && Entity_ClassNameMatches(weapon, exclude)) { Client_SetActiveWeapon(client, weapon); continue; } - + if (clearAmmo) { Client_SetWeaponPlayerAmmoEx(client, weapon, 0, 0); } @@ -1295,7 +1340,7 @@ stock Client_RemoveAllWeapons(client, const String:exclude[]="", bool:clearAmmo= numWeaponsRemoved++; } - + return numWeaponsRemoved; } @@ -1306,10 +1351,10 @@ stock Client_RemoveAllWeapons(client, const String:exclude[]="", bool:clearAmmo= * @param className Weapon Classname. * @return True if client has the weapon, otherwise false. */ -stock Client_HasWeapon(client, const String:className[]) +stock bool:Client_HasWeapon(client, const String:className[]) { new weapon = Client_GetWeapon(client, className); - + return (weapon != INVALID_ENT_REFERENCE); } @@ -1323,21 +1368,21 @@ 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; } - + if (Entity_ClassNameMatches(weapon, className)) { return weapon; } } - + return INVALID_ENT_REFERENCE; } @@ -1367,7 +1412,7 @@ stock Client_GetDefaultWeapon(client) if (Client_GetDefaultWeaponName(client, weaponName, sizeof(weaponName))) { return INVALID_ENT_REFERENCE; } - + return Client_GetWeapon(client, weaponName); } @@ -1387,7 +1432,7 @@ stock bool:Client_GetDefaultWeaponName(client, String:buffer[], size) buffer[0] = '\0'; return false; } - + return true; } @@ -1395,7 +1440,7 @@ stock bool:Client_GetDefaultWeaponName(client, String:buffer[], size) * Gets the first weapon of the client's weapon list (m_hMyWeapons). * Note: This has nothing to do with weapon slots. * - * @param client Client Index. + * @param client Client Index. * @return Entity Index of the weapon or INVALID_ENT_REFERENCE. */ stock Client_GetFirstWeapon(client) @@ -1406,58 +1451,58 @@ stock Client_GetFirstWeapon(client) offset += 4; new weapon = GetEntDataEnt2(client, offset); - + if (!Weapon_IsValid(weapon)) { continue; } - + return weapon; } - + return INVALID_ENT_REFERENCE; } /** * Gets the number of weapons a client has. * - * @param client Client Index. + * @param client Client Index. * @return Number of weapons. */ stock Client_GetWeaponCount(client) -{ +{ new numWeapons = 0; - + new offset = Client_GetWeaponsOffset(client) - 4; for (new i=0; i < MAX_WEAPONS; i++) { offset += 4; new weapon = GetEntDataEnt2(client, offset); - + if (!Weapon_IsValid(weapon)) { continue; } - + numWeapons++; } - + return numWeapons; } /** - * Checks whether the client is currently reloading his active weapon. + * Checks whether the client is currently reloading his active weapon. * - * @param client Client Index. + * @param client Client Index. * @return True if client is reloading, false otherwise. */ stock bool:Client_IsReloading(client) { new weapon = Client_GetActiveWeapon(client); - + if (weapon == INVALID_ENT_REFERENCE) { return false; } - + return Weapon_IsReloading(weapon); } @@ -1505,14 +1550,14 @@ stock bool:Client_GetWeaponPlayerAmmo(client, const String:className[], &primary if (weapon == INVALID_ENT_REFERENCE) { return false; } - - new offset_ammo = FindDataMapOffs(client, "m_iAmmo"); - + + new offset_ammo = FindDataMapInfo(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); @@ -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 = FindDataMapInfo(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. * @@ -1550,11 +1619,11 @@ stock bool:Client_SetWeaponPlayerAmmo(client, const String:className[], primaryA * @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 + * @noreturn */ stock Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo=-1, secondaryAmmo=-1) { - new offset_ammo = FindDataMapOffs(client, "m_iAmmo"); + new offset_ammo = FindDataMapInfo(client, "m_iAmmo"); if (primaryAmmo != -1) { new offset = offset_ammo + (Weapon_GetPrimaryAmmoType(weapon) * 4); @@ -1569,7 +1638,7 @@ stock Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo=-1, secondaryAmmo /** * Sets the value from primary and secondary ammo stock, of a client. - * + * * @param client Client Index. * @param className Classname of a weapon. * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched. @@ -1581,14 +1650,19 @@ stock Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo=-1, secondaryAmmo stock Client_SetWeaponAmmo(client, const String:className[], primaryAmmo=-1, secondaryAmmo=-1, primaryClip=-1, secondaryClip=-1) { new weapon = Client_GetWeapon(client, className); - + if (weapon == INVALID_ENT_REFERENCE) { 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; } @@ -1623,7 +1697,7 @@ stock Client_GetNextWeapon(client, &index = 0) * Prints white text to the bottom center of the screen * for one client. Does not work in all games. * Line Breaks can be done with "\n". - * + * * @param client Client Index. * @param format Formatting rules. * @param ... Variable number of format parameters. @@ -1632,7 +1706,7 @@ stock Client_GetNextWeapon(client, &index = 0) stock bool:Client_PrintHintText(client, const String:format[], any:...) { new Handle:userMessage = StartMessageOne("HintText", client); - + if (userMessage == INVALID_HANDLE) { return false; } @@ -1642,11 +1716,19 @@ 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", buffer); + } + else { + BfWriteByte(userMessage, 1); + BfWriteString(userMessage, buffer); + } EndMessage(); - + return true; } @@ -1654,7 +1736,7 @@ stock bool:Client_PrintHintText(client, const String:format[], any:...) * Prints white text to the bottom center of the screen * for all clients. Does not work in all games. * Line Breaks can be done with "\n". - * + * * @param format Formatting rules. * @param ... Variable number of format parameters. * @noreturn @@ -1662,7 +1744,7 @@ stock bool:Client_PrintHintText(client, const String:format[], any:...) stock Client_PrintHintTextToAll(const String:format[], any:...) { decl String:buffer[254]; - + for (new client=1; client <= MaxClients; client++) { if (!IsClientInGame(client)) { @@ -1679,7 +1761,7 @@ stock Client_PrintHintTextToAll(const String:format[], any:...) * Prints white text to the right-center side of the screen * for one client. Does not work in all games. * Line Breaks can be done with "\n". - * + * * @param client Client Index. * @param format Formatting rules. * @param ... Variable number of format parameters. @@ -1688,7 +1770,7 @@ stock Client_PrintHintTextToAll(const String:format[], any:...) stock bool:Client_PrintKeyHintText(client, const String:format[], any:...) { new Handle:userMessage = StartMessageOne("KeyHintText", client); - + if (userMessage == INVALID_HANDLE) { return false; } @@ -1698,11 +1780,18 @@ 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) { + + PbAddString(userMessage, "hints", buffer); + } + else { + BfWriteByte(userMessage, 1); + BfWriteString(userMessage, buffer); + } EndMessage(); - + return true; } @@ -1710,7 +1799,7 @@ stock bool:Client_PrintKeyHintText(client, const String:format[], any:...) * Prints white text to the right-center side of the screen * for all clients. Does not work in all games. * Line Breaks can be done with "\n". - * + * * @param format Formatting rules. * @param ... Variable number of format parameters. * @noreturn @@ -1718,7 +1807,7 @@ stock bool:Client_PrintKeyHintText(client, const String:format[], any:...) stock Client_PrintKeyHintTextToAll(const String:format[], any:...) { decl String:buffer[254]; - + for (new client=1; client <= MaxClients; client++) { if (!IsClientInGame(client)) { @@ -1766,18 +1855,44 @@ 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(); @@ -1813,7 +1928,7 @@ static printToChat_excludeclient = -1; /** * Exclude a client from the next call to a Client_PrintToChat function. - * + * * @param client Client Index. * @noreturn */ @@ -1826,7 +1941,7 @@ stock Client_PrintToChatExclude(client) * Prints a reliable chat message to all clients in the chat area. * Allows up to 253 Characters (including \0) to be printed. * Supports chat color tags (see: colors.inc). - * + * * @param isChat Tells the game to handle the chat as normal (false) or chat message (true, plays a sound), only works if SayText2 is supported. * @param format Formatting rules String. * @param ... Variable number of format parameters. @@ -1859,7 +1974,7 @@ stock Client_PrintToChatAll(bool:isChat, const String:format[], any:...) SetGlobalTransTarget(client); VFormat(buffer, sizeof(buffer), format, 3); subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2)); - + lastLanguage = language; } @@ -1906,15 +2021,15 @@ stock Client_PrintToChatEx(clients[], numClients, bool:isChat, const String:form } language = GetClientLanguage(client); - + if (language != lastLanguage) { SetGlobalTransTarget(client); VFormat(buffer, sizeof(buffer), format, 5); subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2)); - + lastLanguage = language; } - + Client_PrintToChatRaw(client, buffer2, subject, isChat); } @@ -1942,7 +2057,7 @@ enum ClientHudPrint { stock Client_PrintToConsole(client, const String:format[], any:...) { decl String:buffer[512]; - + SetGlobalTransTarget(client); VFormat(buffer, sizeof(buffer), format, 3); @@ -1975,12 +2090,13 @@ stock Client_Print(client, ClientHudPrint:destination, const String:format[], an return; } + new EngineVersion:engineVersion = GetEngineVersion(); if (client == 0 || - (destination != ClientHudPrint_Console) || - (destination == ClientHudPrint_Console && GuessSDKVersion() < SOURCE_SDK_LEFT4DEAD)) + destination != ClientHudPrint_Console || + (destination == ClientHudPrint_Console + && engineVersion != Engine_Left4Dead && engineVersion != Engine_Left4Dead2)) { - Color_StripFromChatText(buffer, buffer2, sizeof(buffer2)); - strcopy(buffer, sizeof(buffer), buffer2); + Color_StripFromChatText(buffer2, buffer2, sizeof(buffer2)); if (client == 0) { PrintToServer(buffer2); @@ -1991,8 +2107,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(); } @@ -2001,7 +2129,7 @@ stock Client_Print(client, ClientHudPrint:destination, const String:format[], an * Replies to a message in a command. * A client index of 0 will use PrintToServer(). * If the command was from the console, Client_PrintToConsole() is used. - * If the command was from chat, Client_PrintToChat() is used. + * If the command was from chat, Client_PrintToChat() is used. * * @param client Client Index. * @param format Formatting rules String. @@ -2011,7 +2139,7 @@ stock Client_Print(client, ClientHudPrint:destination, const String:format[], an stock Client_Reply(client, const String:format[], any:...) { decl String:buffer[255]; - + SetGlobalTransTarget(client); VFormat(buffer, sizeof(buffer), format, 3); @@ -2033,7 +2161,7 @@ stock Client_Reply(client, const String:format[], any:...) /** * Shakes a client's screen with the specified amptitude, * frequency & duration. - * + * * @param client Client Index. * @param command Shake Mode, use one of the SHAKE_ definitions. * @param amplitude Shake magnitude/amplitude. @@ -2043,23 +2171,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) { - new Handle:userMessage = StartMessageOne("Shake", client); - - if (userMessage == INVALID_HANDLE) { - return false; - } - if (command == SHAKE_STOP) { amplitude = 0.0; } else if (amplitude <= 0.0) { return false; } - - BfWriteByte(userMessage, command); // Shake Command - BfWriteFloat(userMessage, amplitude); // shake magnitude/amplitude - BfWriteFloat(userMessage, frequency); // shake noise frequency - BfWriteFloat(userMessage, duration); // shake lasts this long + + new Handle:userMessage = StartMessageOne("Shake", client); + + if (userMessage == INVALID_HANDLE) { + return false; + } + + 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 { + 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; @@ -2074,11 +2213,11 @@ stock bool:Client_Shake(client, command=SHAKE_START, Float:amplitude=50.0, Float stock bool:Client_IsAdmin(client) { new AdminId:adminId = GetUserAdmin(client); - + if (adminId == INVALID_ADMIN_ID) { return false; } - + return GetAdminFlag(adminId, Admin_Generic); } @@ -2091,11 +2230,11 @@ stock bool:Client_IsAdmin(client) stock bool:Client_HasAdminFlags(client, flags=ADMFLAG_GENERIC) { new AdminId:adminId = GetUserAdmin(client); - + if (adminId == INVALID_ADMIN_ID) { return false; } - + return bool:(GetAdminFlags(adminId, Access_Effective) & flags); } @@ -2130,7 +2269,7 @@ stock bool:Client_IsInAdminGroup(client, const String:groupName[], bool:caseSens for (new i = 0; i < count; i++) { // Get group name. GetAdminGroup(adminId, i, groupname, sizeof(groupname)); - + // Compare names. if (StrEqual(groupName, groupname, caseSensitive)) { return true; @@ -2144,7 +2283,7 @@ stock bool:Client_IsInAdminGroup(client, const String:groupName[], bool:caseSens /** * Checks if the client is currently looking at the wall in front * of him with the given distance as max value. - * + * * @param client Client Index. * @param distance Max Distance as Float value. * @return True if he is looking at a wall, false otherwise. @@ -2153,32 +2292,32 @@ stock bool:Client_IsLookingAtWall(client, Float:distance=40.0) { decl Float:posEye[3], Float:posEyeAngles[3]; new bool:isClientLookingAtWall = false; - + GetClientEyePosition(client, posEye); GetClientEyeAngles(client, posEyeAngles); - + posEyeAngles[0] = 0.0; new Handle:trace = TR_TraceRayFilterEx(posEye, posEyeAngles, CONTENTS_SOLID, RayType_Infinite, _smlib_TraceEntityFilter); - + if (TR_DidHit(trace)) { - + if (TR_GetEntityIndex(trace) > 0) { CloseHandle(trace); return false; } - + decl Float:posEnd[3]; TR_GetEndPosition(posEnd, trace); - - if (GetVectorDistance(posEye, posEnd) <= distance) { + + if (GetVectorDistance(posEye, posEnd, true) <= (distance * distance)) { isClientLookingAtWall = true; } } - + CloseHandle(trace); - + return isClientLookingAtWall; } @@ -2191,14 +2330,14 @@ public bool:_smlib_TraceEntityFilter(entity, contentsMask) * Gets a client's class. * Currently supported games are: TF2, Dark Messiah. * Other games maybe work too, but are not tested. - * + * * @param client Client Index. * @return Class Index. */ stock Client_GetClass(client) { - if (GuessSDKVersion() == SOURCE_SDK_DARKMESSIAH) { - GetEntProp(client, Prop_Send, "m_iPlayerClass"); + if (GetEngineVersion() == Engine_DarkMessiah) { + return GetEntProp(client, Prop_Send, "m_iPlayerClass"); } return GetEntProp(client, Prop_Send, "m_iClass"); @@ -2208,40 +2347,40 @@ stock Client_GetClass(client) * Sets a client's class. * Currently supported games are: TF2, Dark Messiah. * 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"); - } - else { - SetEntProp(client, Prop_Send, "m_iClass", class); - + if (GetEngineVersion() == Engine_DarkMessiah) { + SetEntProp(client, Prop_Send, "m_iPlayerClass", playerClass); + } else { + SetEntProp(client, Prop_Send, "m_iClass", playerClass); + if (persistant) { - SetEntProp(client, Prop_Send, "m_iDesiredPlayerClass", class); + SetEntProp(client, Prop_Send, "m_iDesiredPlayerClass", playerClass); } } } /** * Returns what buttons are currently pressed by the client. - * + * * @param client Client Index. * @return Buttons as bitflag. */ stock Client_GetButtons(client) -{ +{ return GetClientButtons(client); } /** * Sets the client buttons. * Note: This will only work OnPreThink (sdkhooks) or OnPlayerRunCmd. - * + * * @param client Client Index. * @param buttons Buttons as bitflag. * @noreturn @@ -2295,7 +2434,7 @@ stock Client_ClearButtons(client) /** * Returns if the given buttons are pressed by the client or not. - * + * * @param client Client Index. * @param buttons Buttons as bitflag. * @return True if the buttons are pressed otherwise false. @@ -2308,7 +2447,7 @@ stock bool:Client_HasButtons(client, buttons) /** * Returns only the buttons that have changed since the last call of this. * Example usage: Within OnPlayerRunCmd use this function to call another function only once when a player pressed or released a button. - * + * * @param client Client Index. * @param buttons Buttons as bitflag. * @return @@ -2316,12 +2455,12 @@ stock bool:Client_HasButtons(client, buttons) stock Client_GetChangedButtons(client) { static oldButtons[MAXPLAYERS+1] = {0,...}; - + new buttons = Client_GetButtons(client); new changedButtons = buttons ^ oldButtons[client]; - + oldButtons[client] = buttons; - + return changedButtons; } @@ -2526,7 +2665,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 +2739,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/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/colors.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/colors.inc index dcc982eb..4ab0c4d6 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/colors.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/colors.inc @@ -54,7 +54,7 @@ static String:chatColorTags[][] = { "BR", // Blue, Red "T", // Team "L", // Light green - "GRA", // GRAy + "GRA", // GRAy "G", // Green "OG", // Olive green "BLA" // BLAck @@ -69,7 +69,7 @@ static String:chatColorNames[][] = { "bluered", // Blue, Red "team", // Team "lightgreen", // Light green - "gray", // GRAy + "gray", // GRAy "green", // Green "olivegreen", // Olive green "black" // BLAck @@ -86,7 +86,7 @@ static chatColorInfo[][ChatColorInfo] = { '\x03', 2 /* Red */ , true, ChatColorSubjectType:3 }, // Blue, Red { '\x03', 9 /* Green */ , true, ChatColorSubjectType_player }, // Team { '\x03', 9 /* Green */ , true, ChatColorSubjectType_world }, // Light green - { '\x03', 9 /* Green */ , true, ChatColorSubjectType_undefined},// GRAy + { '\x03', 9 /* Green */ , true, ChatColorSubjectType_undefined},// GRAy { '\x04', 0 /* Normal*/ , true, ChatColorSubjectType_none }, // Green { '\x05', 9 /* Green */ , true, ChatColorSubjectType_none }, // Olive green { '\x06', 9 /* Green */ , true, ChatColorSubjectType_none } // BLAck @@ -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') { @@ -151,49 +165,75 @@ stock Color_ParseChatText(const String:str[], String:buffer[], size) break; } - new char = str[x++]; - + new character = str[x++]; + if (inBracket) { - if (char == '}' || x_tag > 2) { - inBracket = false; + // We allow up to 9 characters in the tag (#RRGGBBAA) + if (character == '}' || x_tag > 9) { + inBracket = false; sTag[x_tag] = '\0'; - x_tag = 0; - - if (char == '}') { - code = Color_TagToCode(sTag, subject); - if (code == 0) { - buffer[x_buf+1] = '\0'; + x_tag = 0; + + if (character == '}') { + 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'; - x_buf = Format(buffer, size, "%s{%s%c", buffer, sTag, char); + // 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, character); } } - else if (char == '{' && !x_tag) { + else if (character == '{' && !x_tag) { buffer[x_buf++] = '{'; inBracket = false; } else { - sTag[x_tag++] = char; + sTag[x_tag++] = character; } } - else if (char == '{') { + else if (character == '{') { inBracket = true; } else { - buffer[x_buf++] = char; + buffer[x_buf++] = character; } } + // 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; } /** @@ -230,21 +315,30 @@ stock Color_StripFromChatText(const String:input[], String:output[], size) { new x = 0; for (new i=0; input[i] != '\0'; i++) { - + if (x+1 == size) { break; } - new char = input[i]; - - if (char > 0x08) { - output[x++] = char; + new character = input[i]; + + if (character > 0x08) { + output[x++] = character; } } - + 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) && @@ -309,11 +403,11 @@ static stock Color_ChatInitialize() if (FileExists(path_gamedata)) { new Handle:gamedata = INVALID_HANDLE; - + if ((gamedata = LoadGameConfigFile(SMLIB_COLORS_GAMEDATAFILE)) != INVALID_HANDLE) { decl String:keyName[32], String:buffer[6]; - + for (new i=0; i < sizeof(chatColorNames); i++) { Format(keyName, sizeof(keyName), "%s_code", chatColorNames[i]); @@ -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(); @@ -420,6 +523,6 @@ static stock Color_GetChatColorInfo(&index, &subject=CHATCOLOR_NOSUBJECT) if (subject == CHATCOLOR_NOSUBJECT) { subject = newSubject; } - + return newSubject; } diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/convars.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/convars.inc index 95c40cd3..9b9ba4af 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/convars.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/convars.inc @@ -60,11 +60,11 @@ stock bool:Convar_IsValidName(const String:name[]) new n=0; while (name[n] != '\0') { - + if (!IsValidConVarChar(name[n])) { return false; } - + n++; } diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/crypt.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/crypt.inc index fa9c8f8c..6e5f380d 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/crypt.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/crypt.inc @@ -10,7 +10,7 @@ * Base64 Encoding/Decoding Functions * All Credits to to SirLamer & ScriptCoderPro * Taken from http://forums.alliedmods.net/showthread.php?t=101764 - * + * ***********************************************************************************/ // The Base64 encoding table @@ -69,7 +69,7 @@ static const String:base64_url_chars[] = "-_."; * @param sourcelen (optional): The number of characters or length in bytes to be read from the input source. * This is not needed for a text string, but is important for binary data since there is no end-of-line character. * @return The length of the written Base64 string, in bytes. - */ + */ stock Crypt_Base64Encode(const String:sString[], String:sResult[], len, sourcelen=0) { new nLength; // The string length to be read from the input @@ -239,7 +239,7 @@ stock Crypt_Base64UrlToMime(const String:sString[], String:sResult[], len) nLength = strlen(sString); new String:sTemp[nLength+1]; // Buffer string - + // Loop through string for (new i = 0; i < nLength; i++) { temp_char = sString[i]; @@ -264,12 +264,12 @@ stock Crypt_Base64UrlToMime(const String:sString[], String:sResult[], len) * All Credits go to sslice * RSA Data Security, Inc. MD5 Message Digest Algorithm * Taken from http://forums.alliedmods.net/showthread.php?t=67683 - * + * ***********************************************************************************/ /* * Calculate the md5 hash of a string. - * + * * @param str Input String * @param output Output String Buffer * @param maxlen Size of the Output String Buffer @@ -292,10 +292,10 @@ stock Crypt_MD5(const String:str[], String:output[], maxlen) buf[3] = 0x10325476; // MD5Update - new in[16]; + new update[16]; - in[14] = x[0]; - in[15] = x[1]; + update[14] = x[0]; + update[15] = x[1]; new mdi = (x[0] >>> 3) & 0x3F; @@ -311,17 +311,17 @@ stock Crypt_MD5(const String:str[], String:output[], maxlen) input[mdi] = str[c]; mdi += 1; c += 1; - + if (mdi == 0x40) { for (i = 0, ii = 0; i < 16; ++i, ii += 4) { - in[i] = (input[ii + 3] << 24) | (input[ii + 2] << 16) | (input[ii + 1] << 8) | input[ii]; + update[i] = (input[ii + 3] << 24) | (input[ii + 2] << 16) | (input[ii + 1] << 8) | input[ii]; } // Transform - MD5Transform(buf, in); - + MD5Transform(buf, update); + mdi = 0; } } @@ -345,8 +345,8 @@ stock Crypt_MD5(const String:str[], String:output[], maxlen) mdi = (x[0] >>> 3) & 0x3F; len = (mdi < 56) ? (56 - mdi) : (120 - mdi); - in[14] = x[0]; - in[15] = x[1]; + update[14] = x[0]; + update[15] = x[1]; mdi = (x[0] >>> 3) & 0x3F; @@ -362,16 +362,16 @@ stock Crypt_MD5(const String:str[], String:output[], maxlen) input[mdi] = padding[c]; mdi += 1; c += 1; - + if (mdi == 0x40) { for (i = 0, ii = 0; i < 16; ++i, ii += 4) { - in[i] = (input[ii + 3] << 24) | (input[ii + 2] << 16) | (input[ii + 1] << 8) | input[ii]; + update[i] = (input[ii + 3] << 24) | (input[ii + 2] << 16) | (input[ii + 1] << 8) | input[ii]; } // Transform - MD5Transform(buf, in); - + MD5Transform(buf, update); + mdi = 0; } } @@ -423,80 +423,79 @@ static stock MD5Transform_II(&a, &b, &c, &d, x, s, ac) a += b; } -static stock MD5Transform(buf[], in[]) -{ +static stock MD5Transform(buf[], input[]){ new a = buf[0]; new b = buf[1]; new c = buf[2]; new d = buf[3]; - MD5Transform_FF(a, b, c, d, in[0], 7, 0xd76aa478); - MD5Transform_FF(d, a, b, c, in[1], 12, 0xe8c7b756); - MD5Transform_FF(c, d, a, b, in[2], 17, 0x242070db); - MD5Transform_FF(b, c, d, a, in[3], 22, 0xc1bdceee); - MD5Transform_FF(a, b, c, d, in[4], 7, 0xf57c0faf); - MD5Transform_FF(d, a, b, c, in[5], 12, 0x4787c62a); - MD5Transform_FF(c, d, a, b, in[6], 17, 0xa8304613); - MD5Transform_FF(b, c, d, a, in[7], 22, 0xfd469501); - MD5Transform_FF(a, b, c, d, in[8], 7, 0x698098d8); - MD5Transform_FF(d, a, b, c, in[9], 12, 0x8b44f7af); - MD5Transform_FF(c, d, a, b, in[10], 17, 0xffff5bb1); - MD5Transform_FF(b, c, d, a, in[11], 22, 0x895cd7be); - MD5Transform_FF(a, b, c, d, in[12], 7, 0x6b901122); - MD5Transform_FF(d, a, b, c, in[13], 12, 0xfd987193); - MD5Transform_FF(c, d, a, b, in[14], 17, 0xa679438e); - MD5Transform_FF(b, c, d, a, in[15], 22, 0x49b40821); - - MD5Transform_GG(a, b, c, d, in[1], 5, 0xf61e2562); - MD5Transform_GG(d, a, b, c, in[6], 9, 0xc040b340); - MD5Transform_GG(c, d, a, b, in[11], 14, 0x265e5a51); - MD5Transform_GG(b, c, d, a, in[0], 20, 0xe9b6c7aa); - MD5Transform_GG(a, b, c, d, in[5], 5, 0xd62f105d); - MD5Transform_GG(d, a, b, c, in[10], 9, 0x02441453); - MD5Transform_GG(c, d, a, b, in[15], 14, 0xd8a1e681); - MD5Transform_GG(b, c, d, a, in[4], 20, 0xe7d3fbc8); - MD5Transform_GG(a, b, c, d, in[9], 5, 0x21e1cde6); - MD5Transform_GG(d, a, b, c, in[14], 9, 0xc33707d6); - MD5Transform_GG(c, d, a, b, in[3], 14, 0xf4d50d87); - MD5Transform_GG(b, c, d, a, in[8], 20, 0x455a14ed); - MD5Transform_GG(a, b, c, d, in[13], 5, 0xa9e3e905); - MD5Transform_GG(d, a, b, c, in[2], 9, 0xfcefa3f8); - MD5Transform_GG(c, d, a, b, in[7], 14, 0x676f02d9); - MD5Transform_GG(b, c, d, a, in[12], 20, 0x8d2a4c8a); - - MD5Transform_HH(a, b, c, d, in[5], 4, 0xfffa3942); - MD5Transform_HH(d, a, b, c, in[8], 11, 0x8771f681); - MD5Transform_HH(c, d, a, b, in[11], 16, 0x6d9d6122); - MD5Transform_HH(b, c, d, a, in[14], 23, 0xfde5380c); - MD5Transform_HH(a, b, c, d, in[1], 4, 0xa4beea44); - MD5Transform_HH(d, a, b, c, in[4], 11, 0x4bdecfa9); - MD5Transform_HH(c, d, a, b, in[7], 16, 0xf6bb4b60); - MD5Transform_HH(b, c, d, a, in[10], 23, 0xbebfbc70); - MD5Transform_HH(a, b, c, d, in[13], 4, 0x289b7ec6); - MD5Transform_HH(d, a, b, c, in[0], 11, 0xeaa127fa); - MD5Transform_HH(c, d, a, b, in[3], 16, 0xd4ef3085); - MD5Transform_HH(b, c, d, a, in[6], 23, 0x04881d05); - MD5Transform_HH(a, b, c, d, in[9], 4, 0xd9d4d039); - MD5Transform_HH(d, a, b, c, in[12], 11, 0xe6db99e5); - MD5Transform_HH(c, d, a, b, in[15], 16, 0x1fa27cf8); - MD5Transform_HH(b, c, d, a, in[2], 23, 0xc4ac5665); - - MD5Transform_II(a, b, c, d, in[0], 6, 0xf4292244); - MD5Transform_II(d, a, b, c, in[7], 10, 0x432aff97); - MD5Transform_II(c, d, a, b, in[14], 15, 0xab9423a7); - MD5Transform_II(b, c, d, a, in[5], 21, 0xfc93a039); - MD5Transform_II(a, b, c, d, in[12], 6, 0x655b59c3); - MD5Transform_II(d, a, b, c, in[3], 10, 0x8f0ccc92); - MD5Transform_II(c, d, a, b, in[10], 15, 0xffeff47d); - MD5Transform_II(b, c, d, a, in[1], 21, 0x85845dd1); - MD5Transform_II(a, b, c, d, in[8], 6, 0x6fa87e4f); - MD5Transform_II(d, a, b, c, in[15], 10, 0xfe2ce6e0); - MD5Transform_II(c, d, a, b, in[6], 15, 0xa3014314); - MD5Transform_II(b, c, d, a, in[13], 21, 0x4e0811a1); - MD5Transform_II(a, b, c, d, in[4], 6, 0xf7537e82); - MD5Transform_II(d, a, b, c, in[11], 10, 0xbd3af235); - MD5Transform_II(c, d, a, b, in[2], 15, 0x2ad7d2bb); - MD5Transform_II(b, c, d, a, in[9], 21, 0xeb86d391); + MD5Transform_FF(a, b, c, d, input[0], 7, 0xd76aa478); + MD5Transform_FF(d, a, b, c, input[1], 12, 0xe8c7b756); + MD5Transform_FF(c, d, a, b, input[2], 17, 0x242070db); + MD5Transform_FF(b, c, d, a, input[3], 22, 0xc1bdceee); + MD5Transform_FF(a, b, c, d, input[4], 7, 0xf57c0faf); + MD5Transform_FF(d, a, b, c, input[5], 12, 0x4787c62a); + MD5Transform_FF(c, d, a, b, input[6], 17, 0xa8304613); + MD5Transform_FF(b, c, d, a, input[7], 22, 0xfd469501); + MD5Transform_FF(a, b, c, d, input[8], 7, 0x698098d8); + MD5Transform_FF(d, a, b, c, input[9], 12, 0x8b44f7af); + MD5Transform_FF(c, d, a, b, input[10], 17, 0xffff5bb1); + MD5Transform_FF(b, c, d, a, input[11], 22, 0x895cd7be); + MD5Transform_FF(a, b, c, d, input[12], 7, 0x6b901122); + MD5Transform_FF(d, a, b, c, input[13], 12, 0xfd987193); + MD5Transform_FF(c, d, a, b, input[14], 17, 0xa679438e); + MD5Transform_FF(b, c, d, a, input[15], 22, 0x49b40821); + + MD5Transform_GG(a, b, c, d, input[1], 5, 0xf61e2562); + MD5Transform_GG(d, a, b, c, input[6], 9, 0xc040b340); + MD5Transform_GG(c, d, a, b, input[11], 14, 0x265e5a51); + MD5Transform_GG(b, c, d, a, input[0], 20, 0xe9b6c7aa); + MD5Transform_GG(a, b, c, d, input[5], 5, 0xd62f105d); + MD5Transform_GG(d, a, b, c, input[10], 9, 0x02441453); + MD5Transform_GG(c, d, a, b, input[15], 14, 0xd8a1e681); + MD5Transform_GG(b, c, d, a, input[4], 20, 0xe7d3fbc8); + MD5Transform_GG(a, b, c, d, input[9], 5, 0x21e1cde6); + MD5Transform_GG(d, a, b, c, input[14], 9, 0xc33707d6); + MD5Transform_GG(c, d, a, b, input[3], 14, 0xf4d50d87); + MD5Transform_GG(b, c, d, a, input[8], 20, 0x455a14ed); + MD5Transform_GG(a, b, c, d, input[13], 5, 0xa9e3e905); + MD5Transform_GG(d, a, b, c, input[2], 9, 0xfcefa3f8); + MD5Transform_GG(c, d, a, b, input[7], 14, 0x676f02d9); + MD5Transform_GG(b, c, d, a, input[12], 20, 0x8d2a4c8a); + + MD5Transform_HH(a, b, c, d, input[5], 4, 0xfffa3942); + MD5Transform_HH(d, a, b, c, input[8], 11, 0x8771f681); + MD5Transform_HH(c, d, a, b, input[11], 16, 0x6d9d6122); + MD5Transform_HH(b, c, d, a, input[14], 23, 0xfde5380c); + MD5Transform_HH(a, b, c, d, input[1], 4, 0xa4beea44); + MD5Transform_HH(d, a, b, c, input[4], 11, 0x4bdecfa9); + MD5Transform_HH(c, d, a, b, input[7], 16, 0xf6bb4b60); + MD5Transform_HH(b, c, d, a, input[10], 23, 0xbebfbc70); + MD5Transform_HH(a, b, c, d, input[13], 4, 0x289b7ec6); + MD5Transform_HH(d, a, b, c, input[0], 11, 0xeaa127fa); + MD5Transform_HH(c, d, a, b, input[3], 16, 0xd4ef3085); + MD5Transform_HH(b, c, d, a, input[6], 23, 0x04881d05); + MD5Transform_HH(a, b, c, d, input[9], 4, 0xd9d4d039); + MD5Transform_HH(d, a, b, c, input[12], 11, 0xe6db99e5); + MD5Transform_HH(c, d, a, b, input[15], 16, 0x1fa27cf8); + MD5Transform_HH(b, c, d, a, input[2], 23, 0xc4ac5665); + + MD5Transform_II(a, b, c, d, input[0], 6, 0xf4292244); + MD5Transform_II(d, a, b, c, input[7], 10, 0x432aff97); + MD5Transform_II(c, d, a, b, input[14], 15, 0xab9423a7); + MD5Transform_II(b, c, d, a, input[5], 21, 0xfc93a039); + MD5Transform_II(a, b, c, d, input[12], 6, 0x655b59c3); + MD5Transform_II(d, a, b, c, input[3], 10, 0x8f0ccc92); + MD5Transform_II(c, d, a, b, input[10], 15, 0xffeff47d); + MD5Transform_II(b, c, d, a, input[1], 21, 0x85845dd1); + MD5Transform_II(a, b, c, d, input[8], 6, 0x6fa87e4f); + MD5Transform_II(d, a, b, c, input[15], 10, 0xfe2ce6e0); + MD5Transform_II(c, d, a, b, input[6], 15, 0xa3014314); + MD5Transform_II(b, c, d, a, input[13], 21, 0x4e0811a1); + MD5Transform_II(a, b, c, d, input[4], 6, 0xf7537e82); + MD5Transform_II(d, a, b, c, input[11], 10, 0xbd3af235); + MD5Transform_II(c, d, a, b, input[2], 15, 0x2ad7d2bb); + MD5Transform_II(b, c, d, a, input[9], 21, 0xeb86d391); buf[0] += a; buf[1] += b; @@ -509,7 +508,7 @@ static stock MD5Transform(buf[], in[]) * RC4 Encoding Functions * All Credits go to SirLamer and Raydan * Taken from http://forums.alliedmods.net/showthread.php?t=101834 - * + * ***********************************************************************************/ /* diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/debug.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/debug.inc index d0bc141d..46275ba4 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/debug.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/debug.inc @@ -17,10 +17,10 @@ stock Debug_FloatArray(const Float:array[], size=3) new String:output[64] = ""; for (new i=0; i < size; ++i) { - + if (i > 0 && i < size) { StrCat(output, sizeof(output), ", "); - + } Format(output, sizeof(output), "%s%f", output, array[i]); diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/edicts.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/edicts.inc index 5974939b..376f9759 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/edicts.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/edicts.inc @@ -17,7 +17,7 @@ stock Edict_FindByName(const String:name[]) { new maxEntities = GetMaxEntities(); for (new edict=0; edict < maxEntities; edict++) { - + if (!IsValidEdict(edict)) { continue; } @@ -43,11 +43,11 @@ stock Edict_FindByHammerId(hammerId) { new maxEntities = GetMaxEntities(); for (new edict=0; edict < maxEntities; edict++) { - + if (!IsValidEdict(edict)) { continue; } - + if (Entity_GetHammerId(edict) == hammerId) { return edict; } @@ -65,13 +65,13 @@ stock Edict_FindByHammerId(hammerId) * @return Edict Index or INVALID_ENT_REFERENCE if no entity was found. */ 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; - + if (clientsOnly) { maxEntities = MaxClients; } @@ -80,29 +80,29 @@ stock Edict_GetClosest(Float:vecOrigin_center[3], bool:clientsOnly=false, ignore } for (new edict=1; edict <= maxEntities; edict++) { - + if (!IsValidEdict(edict)) { continue; } - + if (ignoreEntity >= 0 && edict == ignoreEntity) { continue; } - + if (GetEntSendPropOffs(edict, "m_vecOrigin") == -1) { continue; } Entity_GetAbsOrigin(edict, vecOrigin_edict); - - new Float:edict_distance = GetVectorDistance(vecOrigin_center, vecOrigin_edict); - - if (edict_distance < distance) { - distance = edict_distance; + + new Float:edict_distance = GetVectorDistance(vecOrigin_center, vecOrigin_edict, true); + + if (edict_distance < smallestDistance || smallestDistance == 0.0) { + smallestDistance = edict_distance; closestEdict = edict; } } - + return closestEdict; } @@ -114,13 +114,13 @@ stock Edict_GetClosest(Float:vecOrigin_center[3], bool:clientsOnly=false, ignore * @return The closest edict or INVALID_ENT_REFERENCE */ stock Edict_GetClosestToEdict(edict, bool:clientsOnly=false) -{ +{ decl Float:vecOrigin[3]; - + if (GetEntSendPropOffs(edict, "m_vecOrigin") == -1) { return INVALID_ENT_REFERENCE; } - + Entity_GetAbsOrigin(edict, vecOrigin); return Edict_GetClosest(vecOrigin, clientsOnly, edict); diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/effects.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/effects.inc index cefe9f99..c638fd6b 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/effects.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/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); @@ -58,7 +62,7 @@ stock bool:Effect_DissolvePlayerRagDoll(client, DissolveType:dissolveType=DISSOL if (m_hRagdoll == -1) { return false; } - + return Effect_DissolveEntity(m_hRagdoll, dissolveType); } @@ -83,7 +87,7 @@ functag EffectCallback public(entity, any:data); stock Effect_Fade(entity, fadeOut=true, kill=false, fast=true, EffectCallback:callback=INVALID_FUNCTION, any:data=0) { new Float:timerTime = 0.0; - + if (fast) { timerTime = 0.6; @@ -110,10 +114,14 @@ stock Effect_Fade(entity, fadeOut=true, kill=false, fast=true, EffectCallback:ca if (kill || callback != INVALID_FUNCTION) { new Handle:dataPack = INVALID_HANDLE; CreateDataTimer(timerTime, _smlib_Timer_Effect_Fade, dataPack, TIMER_FLAG_NO_MAPCHANGE | TIMER_DATA_HNDL_CLOSE); - + WritePackCell(dataPack, EntIndexToEntRef(entity)); WritePackCell(dataPack, kill); +#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7 + WritePackFunction(dataPack, callback); +#else WritePackCell(dataPack, _:callback); +#endif WritePackCell(dataPack, data); ResetPack(dataPack); } @@ -133,7 +141,7 @@ stock Effect_FadeIn(entity, fast=true, EffectCallback:callback=INVALID_FUNCTION, { Effect_Fade(entity, false, false, fast, callback, data); } - + /** * Fades the entity out. * A wrapper function around Effect_Fade(). @@ -155,9 +163,13 @@ public Action:_smlib_Timer_Effect_Fade(Handle:Timer, Handle:dataPack) { new entity = ReadPackCell(dataPack); new kill = ReadPackCell(dataPack); - new EffectCallback:callback = EffectCallback:ReadPackCell(dataPack); +#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7 + new Function:callback = ReadPackFunction(dataPack); +#else + new Function:callback = Function:ReadPackCell(dataPack); +#endif new any:data = any:ReadPackCell(dataPack); - + if (callback != INVALID_FUNCTION) { Call_StartFunction(INVALID_HANDLE, callback); Call_PushCell(entity); @@ -174,7 +186,7 @@ public Action:_smlib_Timer_Effect_Fade(Handle:Timer, Handle:dataPack) /** * Sends a boxed beam effect to one player. - * + * * Ported from eventscripts vecmath library. * * @param client The client to show the box to. @@ -216,7 +228,7 @@ stock Effect_DrawBeamBoxToClient( /** * Sends a boxed beam effect to all players. - * + * * Ported from eventscripts vecmath library. * * @param bottomCorner One bottom corner of the box. @@ -258,10 +270,10 @@ stock Effect_DrawBeamBoxToAll( /** * 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 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 +316,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 +347,396 @@ 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: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 +) { + new clients[1]; + clients[0] = client; + Effect_DrawAxisOfRotation(clients, 1, origin, angles, length, 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: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 +) +{ + new clients[MaxClients]; + new numClients = Client_Get(clients, CLIENTFILTER_INGAME); + + Effect_DrawAxisOfRotation(clients, numClients, origin, angles, length, 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/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/entities.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/entities.inc index 89708b97..1036dd30 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/entities.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/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,20 +35,20 @@ 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 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++) { - + if (!IsValidEntity(entity)) { continue; } - + if (Entity_NameMatches(entity, name)) { return 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,20 +78,20 @@ 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++) { - + if (!IsValidEntity(entity)) { continue; } - + if (Entity_GetHammerId(entity) == hammerId) { return entity; } @@ -91,8 +99,8 @@ 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; } @@ -111,17 +119,18 @@ stock Entity_FindByHammerId(hammerId, const String:class[]="") * @param classname Classname of the entity to find. * @return Entity index >= 0 if found, -1 otherwise. */ - + stock Entity_FindByClassName(startEntity, const String:className[]) { return FindEntityByClassname(startEntity, 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); } /** @@ -305,7 +308,7 @@ stock Entity_SetParentName(entity, const String:name[], any:...) * @return Hammer ID. */ stock Entity_GetHammerId(entity) -{ +{ return GetEntProp(entity, Prop_Data, "m_iHammerID"); } @@ -341,7 +344,7 @@ stock Entity_SetRadius(entity, Float:radius) */ stock Entity_GetMinSize(entity, Float:vec[3]) { - GetEntPropVector(entity, Prop_Send, "m_vecMins", vec); + GetEntPropVector(entity, Prop_Send, "m_vecMins", vec); } /** @@ -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); } @@ -401,7 +404,7 @@ stock Entity_SetMinMaxSize(entity, Float:vecMins[3], Float:vecMaxs[3]) ThrowError("Error: mins[%d] > maxs[%d] of entity %d", i, i, EntRefToEntIndex(entity)); } } - + decl Float:m_vecMins[3], Float:m_vecMaxs[3]; Entity_GetMinSize(entity, m_vecMins); Entity_GetMaxSize(entity, m_vecMaxs); @@ -412,7 +415,7 @@ stock Entity_SetMinMaxSize(entity, Float:vecMins[3], Float:vecMaxs[3]) Entity_SetMinSize(entity, vecMins); Entity_SetMaxSize(entity, vecMaxs); - + decl Float:vecSize[3]; SubtractVectors(vecMaxs, vecMins, vecSize); Entity_SetRadius(entity, GetVectorLength(vecSize) * 0.5); @@ -443,7 +446,7 @@ stock Entity_SetMinMaxSize(entity, Float:vecMins[3], Float:vecMaxs[3]) #define SF_PHYSPROP_HAS_ATTACHED_RAGDOLLS 0x000800 // Need to remove attached ragdolls on enable motion/etc #define SF_PHYSPROP_FORCE_TOUCH_TRIGGERS 0x001000 // Override normal debris behavior and respond to triggers anyway #define SF_PHYSPROP_FORCE_SERVER_SIDE 0x002000 // Force multiplayer physics object to be serverside -#define SF_PHYSPROP_RADIUS_PICKUP 0x004000 // For Xbox, makes small objects easier to pick up by allowing them to be found +#define SF_PHYSPROP_RADIUS_PICKUP 0x004000 // For Xbox, makes small objects easier to pick up by allowing them to be found #define SF_PHYSPROP_ALWAYS_PICK_UP 0x100000 // Physcannon can always pick this up, no matter what mass or constraints may apply. #define SF_PHYSPROP_NO_COLLISIONS 0x200000 // Don't enable collisions on spawn #define SF_PHYSPROP_IS_GIB 0x400000 // Limit # of active gibs @@ -553,7 +556,7 @@ stock Entity_ClearSpawnFlags(entity) * @return True if the entity has the spawnflags set, false otherwise. */ stock bool:Entity_HasSpawnFlags(entity, flags) -{ +{ return bool:(Entity_GetSpawnFlags(entity) & flags); } @@ -583,7 +586,7 @@ enum Entity_Flags EFL_BOT_FROZEN = (1<<8), // This is set on bots that are frozen. EFL_SERVER_ONLY = (1<<9), // Non-networked entity. EFL_NO_AUTO_EDICT_ATTACH = (1<<10), // Don't attach the edict; we're doing it explicitly - + // Some dirty bits with respect to abs computations EFL_DIRTY_ABSTRANSFORM = (1<<11), EFL_DIRTY_ABSVELOCITY = (1<<12), @@ -674,7 +677,7 @@ stock Entity_RemoveEFlags(entity, Entity_Flags:flags) stock bool:Entity_HasEFlags(entity, Entity_Flags:flags) { new Entity_Flags:currentEFlags = Entity_GetEFlags(entity); - + return bool:(currentEFlags & flags); } @@ -784,7 +787,7 @@ stock Entity_ClearFlags(entity) * NOTE: These numerical values are used in the FGD by the prop code (see prop_dynamic) * Taken from: hl2sdk-ob-valve\public\const.h */ - + enum SolidFlags_t { FSOLID_CUSTOMRAYTEST = 0x0001, // Ignore solid type + always call into the entity for ray tests @@ -821,7 +824,7 @@ stock SolidFlags_t:Entity_GetSolidFlags(entity) * @noreturn */ stock Entity_SetSolidFlags(entity, SolidFlags_t:flags) -{ +{ new SolidFlags_t:oldFlags = Entity_GetSolidFlags(entity); flags = flags & SolidFlags_t:0xFFFF; @@ -829,6 +832,8 @@ stock Entity_SetSolidFlags(entity, SolidFlags_t: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)) != (flags & (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); } /** @@ -957,7 +962,7 @@ stock Entity_GetModel(entity, String:buffer[], size) * * @param entity Entity index * @param model Model name - * @noreturn + * @noreturn */ stock Entity_SetModel(entity, const String:model[]) { @@ -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() @@ -1096,7 +1101,7 @@ stock Entity_SetAbsOrigin(entity, Float:vec[3]) * @param entity Entity index. * @param vec 3 dimensional vector array. * @noreturn - */ + */ stock Entity_GetAbsAngles(entity, Float:vec[3]) { GetEntPropVector(entity, Prop_Data, "m_angAbsRotation", vec); @@ -1108,8 +1113,8 @@ stock Entity_GetAbsAngles(entity, Float:vec[3]) * @param entity Entity index. * @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() @@ -1247,7 +1252,7 @@ stock Entity_UnLock(entity) * @return current health points */ stock Entity_GetHealth(entity) -{ +{ return GetEntProp(entity, Prop_Data, "m_iHealth"); } @@ -1261,10 +1266,10 @@ stock Entity_GetHealth(entity) stock Entity_SetHealth(entity, value, ignoreMax=false, kill=true) { new health = value; - + if (!ignoreMax) { new maxHealth = Entity_GetMaxHealth(entity); - + if (health > maxHealth) { health = maxHealth; } @@ -1273,13 +1278,13 @@ stock Entity_SetHealth(entity, value, ignoreMax=false, kill=true) if (health < 0) { health = 0; } - + SetEntProp(entity, Prop_Data, "m_iHealth", health); if (health <= 0) { Entity_Kill(entity); } - + return health; } @@ -1293,10 +1298,10 @@ stock Entity_SetHealth(entity, value, ignoreMax=false, kill=true) 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); } /** @@ -1309,10 +1314,10 @@ stock Entity_AddHealth(entity, value, ignoreMax=false, kill=true) stock Entity_TakeHealth(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); } /** @@ -1322,7 +1327,7 @@ stock Entity_TakeHealth(entity, value, ignoreMax=false, kill=true) * @return Max health points */ stock Entity_GetMaxHealth(entity) -{ +{ return GetEntProp(entity, Prop_Data, "m_iMaxHealth"); } @@ -1335,7 +1340,7 @@ stock Entity_GetMaxHealth(entity) * @noreturn */ stock Entity_SetMaxHealth(entity, value) -{ +{ SetEntProp(entity, Prop_Data, "m_iMaxHealth", value); return value; } @@ -1352,7 +1357,7 @@ stock Float:Entity_GetDistanceOrigin(entity, const Float:vec[3]) { new Float:entityVec[3]; Entity_GetAbsOrigin(entity, entityVec); - + return GetVectorDistance(entityVec, vec); } @@ -1368,7 +1373,7 @@ stock Float:Entity_GetDistance(entity, target) { new Float:targetVec[3]; Entity_GetAbsOrigin(target, targetVec); - + return Entity_GetDistanceOrigin(entity, targetVec); } @@ -1385,7 +1390,7 @@ stock bool:Entity_InRange(entity, target, Float:distance) if (Entity_GetDistance(entity, target) > distance) { return false; } - + return true; } @@ -1396,7 +1401,7 @@ stock bool:Entity_InRange(entity, target, Float:distance) * @return True on success, false otherwise */ stock bool:Entity_EnableMotion(entity) -{ +{ return AcceptEntityInput(entity, "enablemotion"); } @@ -1464,7 +1469,7 @@ stock Entity_PointAtTarget(entity, target, const String:name[]="") else { strcopy(targetName, sizeof(targetName), name); } - + Entity_SetTargetName(entity, targetName); Entity_SetName(target, targetName); } @@ -1517,7 +1522,7 @@ stock bool:Entity_IsPlayer(entity) if (entity < 1 || entity > MaxClients) { return false; } - + return true; } @@ -1543,17 +1548,23 @@ 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!! ForcePlayerSuicide(kenny); return true; } - - return AcceptEntityInput(kenny, "kill"); + + if(killChildren){ + return AcceptEntityInput(kenny, "KillHierarchy"); + } + else { + return AcceptEntityInput(kenny, "Kill"); + } } /** @@ -1573,7 +1584,7 @@ stock Entity_KillAllByClassName(const String:className[]) AcceptEntityInput(entity, "kill"); x++; } - + return x; } @@ -1619,7 +1630,7 @@ stock Entity_GetGroundEntity(entity) #if !defined DMG_GENERIC #define DMG_GENERIC 0 // generic damage was done -#define DMG_CRUSH (1 << 0) // crushed by falling or moving object. +#define DMG_CRUSH (1 << 0) // crushed by falling or moving object. // NOTE: It's assumed crush damage is occurring as a result of physics collision, so no extra physics force is generated by crush damage. // DON'T use DMG_CRUSH when damaging entities unless it's the result of a physics collision. You probably want DMG_CLUB instead. #define DMG_BULLET (1 << 1) // shot @@ -1631,8 +1642,8 @@ stock Entity_GetGroundEntity(entity) #define DMG_CLUB (1 << 7) // crowbar, punch, headbutt #define DMG_SHOCK (1 << 8) // electric shock #define DMG_SONIC (1 << 9) // sound pulse shockwave -#define DMG_ENERGYBEAM (1 << 10) // laser or other high energy beam -#define DMG_PREVENT_PHYSICS_FORCE (1 << 11) // Prevent a physics force +#define DMG_ENERGYBEAM (1 << 10) // laser or other high energy beam +#define DMG_PREVENT_PHYSICS_FORCE (1 << 11) // Prevent a physics force #define DMG_NEVERGIB (1 << 12) // with this bit OR'd in, no damage type will be able to gib victims upon death #define DMG_ALWAYSGIB (1 << 13) // with this bit OR'd in, any damage type can be made to gib victims upon death. #define DMG_DROWN (1 << 14) // Drowning @@ -1682,39 +1693,39 @@ stock Entity_GetGroundEntity(entity) stock bool:Entity_Hurt(entity, damage, attacker=0, damageType=DMG_GENERIC, const String:fakeClassName[]="") { static point_hurt = INVALID_ENT_REFERENCE; - + if (point_hurt == INVALID_ENT_REFERENCE || !IsValidEntity(point_hurt)) { point_hurt = EntIndexToEntRef(Entity_Create("point_hurt")); - + if (point_hurt == INVALID_ENT_REFERENCE) { return false; } - + DispatchSpawn(point_hurt); } - + AcceptEntityInput(point_hurt, "TurnOn"); SetEntProp(point_hurt, Prop_Data, "m_nDamage", damage); SetEntProp(point_hurt, Prop_Data, "m_bitsDamageType", damageType); Entity_PointHurtAtTarget(point_hurt, entity); - + if (fakeClassName[0] != '\0') { Entity_SetClassName(point_hurt, fakeClassName); } - + AcceptEntityInput(point_hurt, "Hurt", attacker); AcceptEntityInput(point_hurt, "TurnOff"); - + if (fakeClassName[0] != '\0') { Entity_SetClassName(point_hurt, "point_hurt"); } - + return true; } /* * Gets the parent entity of an entity. - * + * * @param entity Entity Index. * @return Entity Index of the parent. */ @@ -1725,11 +1736,11 @@ stock Entity_GetParent(entity) /* * Clears the parent of an entity. - * + * * @param entity Entity Index. * @noreturn */ -stock Entity_RemoveParent(entity) +stock Entity_ClearParent(entity) { SetVariantString(""); AcceptEntityInput(entity, "ClearParent"); @@ -1737,15 +1748,405 @@ stock Entity_RemoveParent(entity) /* * Sets the parent entity of an entity. - * + * * @param entity Entity Index. * @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); +#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7 + WritePackFunction(dataPack, valueCallback); +#else + WritePackCell(dataPack, _:valueCallback); +#endif + 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); +#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7 + new Function:callback = ReadPackFunction(dataPack); +#else + new Function:callback = Function:ReadPackCell(dataPack); +#endif + + 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); +#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7 + WritePackFunction(dataPack, callback); +#else + WritePackCell(dataPack, _:callback); +#endif + 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/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/files.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/files.inc index dc7ffeda..2f56ca06 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/files.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/files.inc @@ -4,7 +4,7 @@ #define _smlib_files_included #include -#include +#include #include /** @@ -19,20 +19,20 @@ * @noreturn */ stock bool:File_GetBaseName(const String:path[], String:buffer[], size) -{ +{ if (path[0] == '\0') { buffer[0] = '\0'; return; } - + new pos_start = FindCharInString(path, '/', true); - + if (pos_start == -1) { pos_start = FindCharInString(path, '\\', true); } - + pos_start++; - + strcopy(buffer, size, path[pos_start]); } @@ -49,23 +49,23 @@ stock bool:File_GetBaseName(const String:path[], String:buffer[], size) * @noreturn */ stock bool:File_GetDirName(const String:path[], String:buffer[], size) -{ +{ if (path[0] == '\0') { buffer[0] = '\0'; return; } - + new pos_start = FindCharInString(path, '/', true); - + if (pos_start == -1) { pos_start = FindCharInString(path, '\\', true); - + if (pos_start == -1) { buffer[0] = '\0'; return; } } - + strcopy(buffer, size, path); buffer[pos_start] = '\0'; } @@ -81,14 +81,14 @@ stock bool:File_GetDirName(const String:path[], String:buffer[], size) * @noreturn */ stock bool:File_GetFileName(const String:path[], String:buffer[], size) -{ +{ if (path[0] == '\0') { buffer[0] = '\0'; return; } - + File_GetBaseName(path, buffer, size); - + new pos_ext = FindCharInString(buffer, '.', true); if (pos_ext != -1) { @@ -110,7 +110,7 @@ stock bool:File_GetFileName(const String:path[], String:buffer[], size) stock File_GetExtension(const String:path[], String:buffer[], size) { new extpos = FindCharInString(path, '.', true); - + if (extpos == -1) { buffer[0] = '\0'; return; @@ -144,14 +144,14 @@ 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)) { return; } - + if (Array_FindString(ignoreExts, size, fileExtension) != -1) { return; } @@ -172,15 +172,15 @@ stock File_AddToDownloadsTable(const String:path[], bool:recursive=true, const S if (StrEqual(dirEntry, ".") || StrEqual(dirEntry, "..")) { continue; } - + Format(dirEntry, sizeof(dirEntry), "%s/%s", path, dirEntry); File_AddToDownloadsTable(dirEntry, recursive, ignoreExts, size); } - + CloseHandle(__dir); } else if (FindCharInString(path, '*', true)) { - + new String:fileExtension[4]; File_GetExtension(path, fileExtension, sizeof(fileExtension)); @@ -227,7 +227,7 @@ stock File_AddToDownloadsTable(const String:path[], bool:recursive=true, const S stock File_ReadDownloadList(const String:path[]) { new Handle:file = OpenFile(path, "r"); - + if (file == INVALID_HANDLE) { return; } @@ -235,13 +235,13 @@ stock File_ReadDownloadList(const String:path[]) new String:buffer[PLATFORM_MAX_PATH]; while (!IsEndOfFile(file)) { ReadFileLine(file, buffer, sizeof(buffer)); - + new pos; pos = StrContains(buffer, "//"); if (pos != -1) { buffer[pos] = '\0'; } - + pos = StrContains(buffer, "#"); if (pos != -1) { buffer[pos] = '\0'; @@ -251,9 +251,9 @@ stock File_ReadDownloadList(const String:path[]) if (pos != -1) { buffer[pos] = '\0'; } - + TrimString(buffer); - + if (buffer[0] == '\0') { continue; } @@ -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/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/game.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/game.inc index b468de9b..771f7805 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/game.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/game.inc @@ -19,7 +19,7 @@ stock bool:Game_End() if (game_end == -1) { game_end = CreateEntityByName("game_end"); - + if (game_end == -1) { ThrowError("Unable to find or create entity \"game_end\""); } @@ -35,7 +35,7 @@ stock bool:Game_End() * * @param team The winning Team, pass 0 for Sudden Death mode (no winning team) * @param forceMapReset If to force the map to reset during the force respawn after the round is over. - * @param switchTeams If to switch the teams when the game is going to be reset. + * @param switchTeams If to switch the teams when the game is going to be reset. * @return True on success, false otherwise */ stock bool:Game_EndRound(team=0, bool:forceMapReset=false, bool:switchTeams=false) @@ -43,7 +43,7 @@ stock bool:Game_EndRound(team=0, bool:forceMapReset=false, bool:switchTeams=fals new game_round_win = FindEntityByClassname(-1, "game_round_win"); if (game_round_win == -1) { - game_round_win = CreateEntityByName("game_end"); + game_round_win = CreateEntityByName("game_round_win"); if (game_round_win == -1) { ThrowError("Unable to find or create entity \"game_round_win\""); diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/general.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/general.inc index 1a0b4026..ef061b6e 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/general.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/general.inc @@ -14,7 +14,7 @@ /* * Precaches the given model. * It's best to call this OnMapStart(). - * + * * @param material Path of the material to precache. * @return Returns the material index, INVALID_STRING_INDEX on error. */ @@ -27,24 +27,24 @@ stock PrecacheMaterial(const String:material[]) return INVALID_STRING_INDEX; } } - + new index = FindStringIndex2(materialNames, material); if (index == INVALID_STRING_INDEX) { new numStrings = GetStringTableNumStrings(materialNames); if (numStrings >= GetStringTableMaxStrings(materialNames)) { return INVALID_STRING_INDEX; } - + AddToStringTable(materialNames, material); index = numStrings; } - + return index; } /* * Checks if the material is precached. - * + * * @param material Path of the material. * @return True if it is precached, false otherwise. */ @@ -57,7 +57,7 @@ stock bool:IsMaterialPrecached(const String:material[]) return false; } } - + return (FindStringIndex2(materialNames, material) != INVALID_STRING_INDEX); } @@ -65,7 +65,7 @@ stock bool:IsMaterialPrecached(const String:material[]) * Precaches the given particle system. * It's best to call this OnMapStart(). * Code based on Rochellecrab's, thanks. - * + * * @param particleSystem Name of the particle system to precache. * @return Returns the particle system index, INVALID_STRING_INDEX on error. */ @@ -85,17 +85,17 @@ stock PrecacheParticleSystem(const String:particleSystem[]) if (numStrings >= GetStringTableMaxStrings(particleEffectNames)) { return INVALID_STRING_INDEX; } - + AddToStringTable(particleEffectNames, particleSystem); index = numStrings; } - + return index; } /* * Checks if the particle system is precached. - * + * * @param material Name of the particle system * @return True if it is precached, false otherwise. */ @@ -108,13 +108,13 @@ stock bool:IsParticleSystemPrecached(const String:particleSystem[]) return false; } } - + return (FindStringIndex2(particleEffectNames, particleSystem) != INVALID_STRING_INDEX); } /* - * Searches for the index of a given string in a string table. - * + * Searches for the index of a given string in a string table. + * * @param table String table name. * @param str String to find. * @return String index if found, INVALID_STRING_INDEX otherwise. @@ -125,15 +125,15 @@ stock FindStringIndexByTableName(const String:table[], const String:str[]) if ((tableIndex = FindStringTable("ParticleEffectNames")) == INVALID_STRING_TABLE) { return INVALID_STRING_INDEX; } - + return FindStringIndex2(tableIndex, str); } /* * Rewrite of FindStringIndex, because in my tests * FindStringIndex failed to work correctly. - * Searches for the index of a given string in a string table. - * + * Searches for the index of a given string in a string table. + * * @param tableidx A string table index. * @param str String to find. * @return String index if found, INVALID_STRING_INDEX otherwise. @@ -145,18 +145,18 @@ stock FindStringIndex2(tableidx, const String:str[]) new numStrings = GetStringTableNumStrings(tableidx); for (new i=0; i < numStrings; i++) { ReadStringTable(tableidx, i, buf, sizeof(buf)); - + if (StrEqual(buf, str)) { return i; } } - + return INVALID_STRING_INDEX; } /* * Converts a long IP to a dotted format String. - * + * * @param ip IP Long * @param buffer String Buffer (size = 16) * @param size String Buffer size @@ -176,7 +176,7 @@ stock LongToIP(ip, String:buffer[], size) /* * Converts a dotted format String IP to a long. - * + * * @param ip IP String * @return Long IP */ @@ -196,7 +196,7 @@ stock IPToLong(const String:ip[]) ); } -static localIPRanges[] = +static localIPRanges[] = { 10 << 24, // 10. 127 << 24 | 1 , // 127.0.0.1 @@ -206,7 +206,7 @@ static localIPRanges[] = /* * Checks whether an IP is a private/internal IP - * + * * @param ip IP Long * @return True if the IP is local, false otherwise. */ @@ -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/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/math.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/math.inc index beec68e7..8acca989 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/math.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/math.inc @@ -5,12 +5,14 @@ #include -#define SIZE_OF_INT 2147483647 // without 0 +#define SIZE_OF_INT 2147483647 // without 0 +#define INT_MAX_DIGITS 10 #define GAMEUNITS_TO_METERS 0.01905 #define METERS_TO_GAMEUNITS 52.49343832020997 #define METERS_TO_FEET 3.2808399 #define FEET_TO_METERS 0.3048 +#define KILOMETERS_TO_MILES 0.62137 enum VecAngle { @@ -21,22 +23,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) -{ - if (number >= 0) { - return number; - } - - return (number * -1); +stock Math_Abs(value) +{ + 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) @@ -44,16 +44,16 @@ stock any:Math_Abs(any:number) * @return True if vectors are equal, false otherwise. */ stock bool:Math_VectorsEqual(Float:vec1[3], Float:vec2[3], Float:tolerance=0.0) -{ - new Float:distance = GetVectorDistance(vec1, vec2); - - return distance <= tolerance; +{ + new Float:distance = GetVectorDistance(vec1, vec2, true); + + return distance <= (tolerance * tolerance); } /** * Sets the given value to min * if the value is smaller than the given. - * + * * @param value Value * @param min Min Value used as lower border * @return Correct value not lower than min @@ -63,24 +63,24 @@ stock any:Math_Min(any:value, any:min) if (value < min) { value = min; } - + return value; } /** * Sets the given value to max * if the value is greater than the given. - * + * * @param value Value * @param max Max Value used as upper border * @return Correct value not upper than max */ stock any:Math_Max(any:value, any:max) -{ +{ if (value > max) { value = max; } - + return value; } @@ -90,7 +90,7 @@ stock any:Math_Max(any:value, any:max) * If the value is outside the range it is set to either * min or max, if it is inside the range it will just return * the specified value. - * + * * @param value Value * @param min Min value used as lower border * @param max Max value used as upper border @@ -104,9 +104,9 @@ stock any:Math_Clamp(any:value, any:min, any:max) return value; } -/* +/* * Checks if the value is within the given bounds (min & max). - * + * * @param value The value you want to check. * @param min The lower border. * @param max The upper border. @@ -117,7 +117,7 @@ stock bool:Math_IsInBounds(any:value, any:min, any:max) if (value < min || value > max) { return false; } - + return true; } @@ -125,7 +125,7 @@ stock bool:Math_IsInBounds(any:value, any:min, any:max) * Let's the specified value "overflow" if it is outside the given limit. * This is like with integers when it reaches a value above the max possible * integer size. - * + * * @param value Value * @param min Min value used as lower border * @param max Max value used as upper border @@ -141,7 +141,7 @@ stock any:Math_Overflow(any:value, any:min, any:max) * This is safe to use multiple times in a function. * The seed is set automatically for each plugin. * Rewritten by MatthiasVance, thanks. - * + * * @param min Min value used as lower border * @param max Max value used as upper border * @return Random Integer number between min and max @@ -149,7 +149,7 @@ stock any:Math_Overflow(any:value, any:min, any:max) stock Math_GetRandomInt(min, max) { new random = GetURandomInt(); - + if (random == 0) { random++; } @@ -161,7 +161,7 @@ stock Math_GetRandomInt(min, max) * Returns a random, uniform Float number in the specified (inclusive) range. * This is safe to use multiple times in a function. * The seed is set automatically for each plugin. - * + * * @param min Min value used as lower border * @param max Max value used as upper border * @return Random Float number between min and max @@ -175,7 +175,7 @@ stock Float:Math_GetRandomFloat(Float:min, Float:max) * Gets the percentage of amount in all as Integer where * amount and all are numbers and amount usually * is a subset of all. - * + * * @param value Integer value * @param all Integer value * @return An Integer value between 0 and 100 (inclusive). @@ -188,7 +188,7 @@ stock Math_GetPercentage(value, all) { * Gets the percentage of amount in all as Float where * amount and all are numbers and amount usually * is a subset of all. - * + * * @param value Float value * @param all Float value * @return A Float value between 0.0 and 100.0 (inclusive). @@ -215,9 +215,82 @@ 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 - * + * * @param units Float value * @return Meters as Float value. */ @@ -228,7 +301,7 @@ stock Float:Math_UnitsToMeters(Float:units) /** * Converts Source Game Units to Meters - * + * * @param units Float value * @return Feet as Float value. */ @@ -236,3 +309,36 @@ stock Float:Math_UnitsToFeet(Float:units) { return (Math_UnitsToMeters(units) * METERS_TO_FEET); } + +/** + * Converts Source Game Units to Centimeters + * + * @param units Float value + * @return Centimeters as Float value. + */ +stock Float:Math_UnitsToCentimeters(Float:units) +{ + return (Math_UnitsToMeters(units) * 100.0); +} + +/** + * Converts Source Game Units to Kilometers + * + * @param units Float value + * @return Kilometers as Float value. + */ +stock Float:Math_UnitsToKilometers(Float:units) +{ + return (Math_UnitsToMeters(units) / 1000.0); +} + +/** + * Converts Source Game Units to Miles + * + * @param units Float value + * @return Miles as Float value. + */ +stock Float:Math_UnitsToMiles(Float:units) +{ + return (Math_UnitsToKilometers(units) * KILOMETERS_TO_MILES); +} diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/menus.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/menus.inc new file mode 100644 index 00000000..c0c825db --- /dev/null +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/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/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/server.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/server.inc index 5ae18378..cb439e2b 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/server.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/server.inc @@ -13,7 +13,7 @@ * extension available at http://forums.alliedmods.net/showthread.php?t=129763 * to get the public IP. has to be included BEFORE . * If the server is not behind NAT, the public IP is the same as the private IP. - * + * * @param public Set to true to retrieve the server's public/external IP, false otherwise. * @return Long IP or 0 if the IP couldn't be retrieved. */ @@ -66,7 +66,7 @@ stock Server_GetIP(bool:public_=true) * to get the public IP. has to be included BEFORE . * If the public IP couldn't be found, an empty String is returned. * If the server is not behind NAT, the public IP is the same as the private IP. - * + * * @param buffer String buffer (size=16) * @param size String buffer size. * @param public Set to true to retrieve the server's public/external IP, false otherwise. @@ -75,7 +75,7 @@ stock Server_GetIP(bool:public_=true) stock bool:Server_GetIPString(String:buffer[], size, bool:public_=true) { new ip; - + if ((ip = Server_GetIP(public_)) == 0) { buffer[0] = '\0'; return false; @@ -95,7 +95,7 @@ stock bool:Server_GetIPString(String:buffer[], size, bool:public_=true) stock Server_GetPort() { static Handle:cvHostport = INVALID_HANDLE; - + if (cvHostport == INVALID_HANDLE) { cvHostport = FindConVar("hostport"); } @@ -117,9 +117,9 @@ stock Server_GetPort() * @return True on success, false otherwise. */ stock bool:Server_GetHostName(String:buffer[], size) -{ +{ static Handle:cvHostname = INVALID_HANDLE; - + if (cvHostname == INVALID_HANDLE) { cvHostname = FindConVar("hostname"); } diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/sql.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/sql.inc index 7e399327..1a4f1f12 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/sql.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/sql.inc @@ -9,7 +9,7 @@ /** * Executes a threaded SQL Query (See: SQL_TQuery) * This function supports the printf Syntax. - * + * * * @param database A database Handle. * @param callback Callback; database is in "owner" and the query Handle is passed in "hndl". @@ -25,11 +25,11 @@ stock SQL_TQueryF(Handle:database, SQLTCallback:callback, any:data, DBPriority:p ThrowError("[SMLIB] Error: Invalid database handle."); return; } - + 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); } /** @@ -44,10 +44,10 @@ stock SQL_TQueryF(Handle:database, SQLTCallback:callback, any:data, DBPriority:p * or no current result set. */ stock SQL_FetchIntByName(Handle:query, String:fieldName[], &DBResult:result=DBVal_Error) { - + new fieldNum; SQL_FieldNameToNum(query, fieldName, fieldNum); - + return SQL_FetchInt(query, fieldNum, result); } @@ -63,13 +63,13 @@ stock SQL_FetchIntByName(Handle:query, String:fieldName[], &DBResult:result=DBVa * or no current result set. */ stock bool:SQL_FetchBoolByName(Handle:query, String:fieldName[], &DBResult:result=DBVal_Error) { - + return bool:SQL_FetchIntByName(query, fieldName, result); } /** * Fetches a float from a field in the current row of a result set. (See: SQL_FetchFloat) - * + * * @param query A query (or statement) Handle. * @param field The field index (starting from 0). * @param result Optional variable to store the status of the return value. @@ -79,16 +79,16 @@ stock bool:SQL_FetchBoolByName(Handle:query, String:fieldName[], &DBResult:resul * or no current result set. */ stock Float:SQL_FetchFloatByName(Handle:query, String:fieldName[], &DBResult:result=DBVal_Error) { - + new fieldNum; SQL_FieldNameToNum(query, fieldName, fieldNum); - + return SQL_FetchFloat(query, fieldNum, result); } /** * Fetches a string from a field in the current row of a result set. (See: SQL_FetchString) - * + * * @param query A query (or statement) Handle. * @param field The field index (starting from 0). * @param buffer String buffer. @@ -100,9 +100,9 @@ stock Float:SQL_FetchFloatByName(Handle:query, String:fieldName[], &DBResult:res * or no current result set. */ stock SQL_FetchStringByName(Handle:query, String:fieldName[], String:buffer[], maxlength, &DBResult:result=DBVal_Error) { - + new fieldNum; SQL_FieldNameToNum(query, fieldName, fieldNum); - + return SQL_FetchString(query, fieldNum, buffer, maxlength, result); } diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/strings.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/strings.inc index 4a3754e1..96657f90 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/strings.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/strings.inc @@ -14,7 +14,7 @@ * @return True if the String is numeric, false otherwise.. */ stock bool:String_IsNumeric(const String:str[]) -{ +{ new x=0; new dotsFound=0; new numbersFound=0; @@ -30,7 +30,7 @@ stock bool:String_IsNumeric(const String:str[]) } else if (str[x] == '.') { dotsFound++; - + if (dotsFound > 1) { return false; } @@ -38,14 +38,14 @@ stock bool:String_IsNumeric(const String:str[]) else { return false; } - + x++; } - + if (!numbersFound) { return false; } - + return true; } @@ -61,19 +61,19 @@ stock bool:String_IsNumeric(const String:str[]) * @noreturn */ stock String_Trim(const String:str[], String:output[], size, const String:chrs[]=" \t\r\n") -{ +{ new x=0; while (str[x] != '\0' && FindCharInString(chrs, str[x]) != -1) { x++; } - + x = strcopy(output, size, str[x]); x--; while (x >= 0 && FindCharInString(chrs, output[x]) != -1) { x--; } - + output[++x] = '\0'; } @@ -87,7 +87,7 @@ stock String_Trim(const String:str[], String:output[], size, const String:chrs[] * @noreturn */ stock String_RemoveList(String:buffer[], String:removeList[][], size, bool:caseSensitive=false) -{ +{ for (new i=0; i < size; i++) { ReplaceString(buffer, SIZE_OF_INT, removeList[i], "", caseSensitive); } @@ -95,7 +95,7 @@ stock String_RemoveList(String:buffer[], String:removeList[][], size, bool:caseS /** * Converts the whole String to lower case. - * Only works with alphabetical characters (not ÖÄÜ) because Sourcemod suxx ! + * Only works with alphabetical characters (not ÖÄÜ) because Sourcemod suxx ! * The Output String can be the same as the Input String. * * @param input Input String. @@ -108,15 +108,10 @@ stock String_ToLower(const String:input[], String:output[], size) size--; new x=0; - while (input[x] != '\0' || x < size) { - - if (IsCharUpper(input[x])) { - output[x] = CharToLower(input[x]); - } - else { - output[x] = input[x]; - } - + while (input[x] != '\0' && x < size) { + + output[x] = CharToLower(input[x]); + x++; } @@ -125,7 +120,7 @@ stock String_ToLower(const String:input[], String:output[], size) /** * Converts the whole String to upper case. - * Only works with alphabetical characters (not öäü) because Sourcemod suxx ! + * Only works with alphabetical characters (not öäü) because Sourcemod suxx ! * The Output String can be the same as the Input String. * * @param input Input String. @@ -138,14 +133,9 @@ stock String_ToUpper(const String:input[], String:output[], size) size--; new x=0; - while (input[x] != '\0') { - - if (IsCharLower(input[x])) { - output[x] = CharToUpper(input[x]); - } - else { - output[x] = input[x]; - } + while (input[x] != '\0' && x < size) { + + output[x] = CharToUpper(input[x]); x++; } @@ -155,7 +145,7 @@ stock String_ToUpper(const String:input[], String:output[], size) /** * Generates a random string. - * + * * * @param buffer String Buffer. * @param size String Buffer size (must be length+1) @@ -169,7 +159,7 @@ stock String_GetRandom(String:buffer[], size, length=32, const String:chrs[]="ab { new random, len; size--; - + if (chrs[0] != '\0') { len = strlen(chrs) - 1; } @@ -185,9 +175,59 @@ stock String_GetRandom(String:buffer[], size, length=32, const String:chrs[]="ab random = Math_GetRandomInt(0, len); buffer[n] = chrs[random]; } - + n++; } 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 (subString[n] != '\0') { + + if (str[n] == '\0' || 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; + + if(n_str < n_subString) { + return false; + } + + while (n_str != 0 && n_subString != 0) { + + if (str[n_str--] != subString[n_subString--]) { + return false; + } + } + + return true; +} diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/teams.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/teams.inc index 91defbed..2fd18c86 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/teams.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/teams.inc @@ -20,21 +20,21 @@ #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. + * @return True if one team is empty, false otherwise. */ 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; } } - + return true; } @@ -105,14 +105,14 @@ stock Team_GetClientCounts(&team1=0, &team2=0, flags=0) stock bool:Team_GetName(index, String:str[], size) { new edict = Team_GetEdict(index); - + if (edict == -1) { str[0] = '\0'; return false; } GetEntPropString(edict, Prop_Send, "m_szTeamname", str, size); - + return true; } @@ -129,14 +129,14 @@ stock bool:Team_GetName(index, String:str[], size) stock bool:Team_SetName(index, const String:name[]) { new edict = Team_GetEdict(index); - + if (edict == -1) { return false; } SetEntPropString(edict, Prop_Send, "m_szTeamname", name); ChangeEdictState(edict, GetEntSendPropOffs(edict, "m_szTeamname", true)); - + return true; } @@ -150,7 +150,7 @@ stock bool:Team_SetName(index, const String:name[]) stock Team_GetScore(index) { new edict = Team_GetEdict(index); - + if (edict == -1) { return -1; } @@ -169,15 +169,15 @@ stock Team_GetScore(index) stock bool:Team_SetScore(index, score) { new edict = Team_GetEdict(index); - + if (edict == -1) { return false; } SetEntProp(edict, Prop_Send, "m_iScore", score); - + ChangeEdictState(edict, GetEntSendPropOffs(edict, "m_iScore", true)); - + return true; } @@ -289,7 +289,7 @@ stock Team_GetAnyClient(index) client = client_cache[index]; if (client > 0 && client <= MaxClients) { - + if (IsClientInGame(client) && GetClientTeam(client) == index) { return client; } @@ -300,11 +300,11 @@ stock Team_GetAnyClient(index) } for (client=1; client <= MaxClients; client++) { - + if (!IsClientInGame(client)) { continue; } - + if (GetClientTeam(client) != index) { continue; } @@ -313,6 +313,6 @@ stock Team_GetAnyClient(index) return client; } - + return -1; } diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/vehicles.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/vehicles.inc index fc4c9179..d9fdebd5 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/vehicles.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/vehicles.inc @@ -44,7 +44,7 @@ stock bool:Vehicle_ExitDriver(vehicle) if (!Vehicle_HasDriver(vehicle)) { return false; } - + return AcceptEntityInput(vehicle, "ExitVehicle"); } @@ -56,7 +56,7 @@ stock bool:Vehicle_ExitDriver(vehicle) */ stock bool:Vehicle_TurnOn(vehicle) { - + return AcceptEntityInput(vehicle, "TurnOn"); } @@ -68,7 +68,7 @@ stock bool:Vehicle_TurnOn(vehicle) */ stock bool:Vehicle_TurnOff(vehicle) { - + return AcceptEntityInput(vehicle, "TurnOff"); } @@ -80,7 +80,7 @@ stock bool:Vehicle_TurnOff(vehicle) */ stock bool:Vehicle_Lock(vehicle) { - + return AcceptEntityInput(vehicle, "Lock"); } @@ -92,7 +92,7 @@ stock bool:Vehicle_Lock(vehicle) */ stock bool:Vehicle_Unlock(vehicle) { - + return AcceptEntityInput(vehicle, "Unlock"); } @@ -107,7 +107,7 @@ stock bool:Vehicle_IsValid(vehicle) if (!Entity_IsValid(vehicle)) { return false; } - + return Entity_ClassNameMatches(vehicle, "prop_vehicle", true); } @@ -130,7 +130,7 @@ stock bool:Vehicle_GetScript(vehicle, String:buffer[], size) * Sets the script of a vehicle. * This script contains all the vehicle settings like its speed * and that stuff. - * + * * @param vehicle Entity index. * @param buffer Vehicle Script path. * @noreturn diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/weapons.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/weapons.inc index 207bcf66..757119d7 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/weapons.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/weapons.inc @@ -21,7 +21,7 @@ /* * Gets the owner (usually a client) of the weapon - * + * * @param weapon Weapon Entity. * @return Owner of the weapon or INVALID_ENT_REFERENCE if the weapon has no owner. */ @@ -32,7 +32,7 @@ stock Weapon_GetOwner(weapon) /* * Sets the owner (usually a client) of the weapon - * + * * @param weapon Weapon Entity. * @param entity Entity Index. * @noreturn @@ -44,7 +44,7 @@ stock Weapon_SetOwner(weapon, entity) /* * Checks whether the entity is a valid weapon or not. - * + * * @param weapon Weapon Entity. * @return True if the entity is a valid weapon, false otherwise. */ @@ -59,7 +59,7 @@ stock Weapon_IsValid(weapon) /* * Create's a weapon and spawns it in the world at the specified location. - * + * * @param className Classname String of the weapon to spawn * @param absOrigin Absolute Origin Vector where to spawn the weapon. * @param absAngles Absolute Angles Vector. @@ -68,22 +68,22 @@ stock Weapon_IsValid(weapon) stock Weapon_Create(const String:className[], Float:absOrigin[3], Float:absAngles[3]) { new weapon = Entity_Create(className); - + if (weapon == INVALID_ENT_REFERENCE) { return INVALID_ENT_REFERENCE; } - + Entity_SetAbsOrigin(weapon, absOrigin); Entity_SetAbsAngles(weapon, absAngles); - + DispatchSpawn(weapon); - + return weapon; } /* * Create's a weapon and spawns it in the world at the specified location. - * + * * @param className Classname String of the weapon to spawn * @param absOrigin Absolute Origin Vector where to spawn the weapon. * @param absAngles Absolute Angles Vector. @@ -94,33 +94,33 @@ stock Weapon_CreateForOwner(client, const String:className[]) decl Float:absOrigin[3], Float:absAngles[3]; Entity_GetAbsOrigin(client, absOrigin); Entity_GetAbsAngles(client, absAngles); - + new weapon = Weapon_Create(className, absOrigin, absAngles); - + if (weapon == INVALID_ENT_REFERENCE) { return INVALID_ENT_REFERENCE; } Entity_SetOwner(weapon, client); - + return weapon; } /* * Gets the weapon's subtype. * The subtype is only used when a player has multiple weapons of the same type. - * + * * @param weapon Weapon Entity. * @return Subtype of the weapon. */ -stock Weapon_GetSubType(weapon, value) +stock Weapon_GetSubType(weapon) { return GetEntProp(weapon, Prop_Data, "m_iSubType"); } /* * Is the weapon currently reloading ? - * + * * @param weapon Weapon Entity. * @return True if weapon is currently reloading, false if not. */ @@ -141,7 +141,7 @@ stock bool:Weapon_IsReloading(weapon) * Get's the state of the weapon. * This returns whether the weapon is currently carried by a client, * if it is active and if it is on a target. - * + * * @param weapon Weapon Entity. * @return Weapon State. */ @@ -152,7 +152,7 @@ stock Weapon_GetState(weapon) /* * Returns whether the weapon can fire primary ammo under water. - * + * * @param weapon Weapon Entity. * @return True or False. */ @@ -163,7 +163,7 @@ stock bool:Weapon_FiresUnderWater(weapon) /* * Sets if the weapon can fire primary ammo under water. - * + * * @param weapon Weapon Entity. * @param can True or False. * @noreturn @@ -175,7 +175,7 @@ stock Weapon_SetFiresUnderWater(weapon, bool:can=true) /* * Returns whether the weapon can fire secondary ammo under water. - * + * * @param weapon Weapon Entity. * @return True or False. */ @@ -186,7 +186,7 @@ stock bool:Weapon_FiresUnderWaterAlt(weapon) /* * Sets if the weapon can fire secondary ammo under water. - * + * * @param weapon Weapon Entity. * @param can True or False. * @noreturn @@ -198,7 +198,7 @@ stock Weapon_SetFiresUnderWaterAlt(weapon, bool:can=true) /* * Gets the primary ammo Type (int offset) - * + * * @param weapon Weapon Entity. * @return Primary ammo type value. */ @@ -207,9 +207,20 @@ 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) +{ + SetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoType", type); +} + /* * Gets the secondary ammo Type (int offset) - * + * * @param weapon Weapon Entity. * @return Secondary ammo type value. */ @@ -218,9 +229,20 @@ 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) +{ + SetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoType", type); +} + /* * Gets the primary clip count of a weapon. - * + * * @param weapon Weapon Entity. * @return Primary Clip count. */ @@ -231,7 +253,7 @@ stock Weapon_GetPrimaryClip(weapon) /* * Sets the primary clip count of a weapon. - * + * * @param weapon Weapon Entity. * @param value Clip Count value. */ @@ -242,7 +264,7 @@ stock Weapon_SetPrimaryClip(weapon, value) /* * Gets the secondary clip count of a weapon. - * + * * @param weapon Weapon Entity. * @return Secondy Clip count. */ @@ -253,7 +275,7 @@ stock Weapon_GetSecondaryClip(weapon) /* * Sets the secondary clip count of a weapon. - * + * * @param weapon Weapon Entity. * @param value Clip Count value. */ @@ -264,7 +286,7 @@ stock Weapon_SetSecondaryClip(weapon, value) /* * Sets the primary & secondary clip count of a weapon. - * + * * @param weapon Weapon Entity. * @param primary Primary Clip Count value. * @param secondary Primary Clip Count value. @@ -280,7 +302,7 @@ stock Weapon_SetClips(weapon, primary, secondary) * This is only used when the weapon is not carried * by a player to give a player ammo when he picks up * the weapon. - * + * * @param weapon Weapon Entity. * @return Primary Ammo Count. */ @@ -294,7 +316,7 @@ stock Weapon_GetPrimaryAmmoCount(weapon) * This is only used when the weapon is not carried * by a player to give a player ammo when he picks up * the weapon. - * + * * @param weapon Weapon Entity. * @param value Primary Ammo Count. * @noreturn @@ -309,7 +331,7 @@ stock Weapon_SetPrimaryAmmoCount(weapon, value) * This is only used when the weapon is not carried * by a player to give a player ammo when he picks up * the weapon. - * + * * @param weapon Weapon Entity. * @return Secondary Ammo Count. */ @@ -323,7 +345,7 @@ stock Weapon_GetSecondaryAmmoCount(weapon) * This is only used when the weapon is not carried * by a player to give a player ammo when he picks up * the weapon. - * + * * @param weapon Weapon Entity. * @param value Secondary Ammo Count. * @noreturn @@ -338,7 +360,7 @@ stock Weapon_SetSecondaryAmmoCount(weapon, value) * This is only used when the weapon is not carried * by a player to give a player ammo when he picks up * the weapon. - * + * * @param weapon Weapon Entity. * @value primary Primary Ammo Count. * @value secondary Secondary Ammo Count. @@ -352,7 +374,7 @@ stock Weapon_SetAmmoCounts(weapon, primary, secondary) /* * Gets the Model Index of the weapon's view model. - * + * * @param weapon Weapon Entity. * @return View Model Index. */ @@ -364,7 +386,7 @@ stock Weapon_GetViewModelIndex(weapon) /* * Sets the Model Index of the weapon's view model. * You can get the Model Index by precaching a model with PrecacheModel(). - * + * * @param weapon Weapon Entity. * @param index Model Index. * @noreturn @@ -372,6 +394,5 @@ stock Weapon_GetViewModelIndex(weapon) stock Weapon_SetViewModelIndex(weapon, index) { SetEntProp(weapon, Prop_Data, "m_nViewModelIndex", index); - ChangeEdictState(weapon, FindDataMapOffs(weapon, "m_nViewModelIndex")); + ChangeEdictState(weapon, FindDataMapInfo(weapon, "m_nViewModelIndex")); } - diff --git a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/world.inc b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/world.inc index a9b47b54..cd14b951 100644 --- a/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/world.inc +++ b/Resources/Misc/Configurations/sm_1_8_5914_smlib_0_11/include/smlib/world.inc @@ -9,9 +9,9 @@ * Gets the world's max size * * @param vec Vector buffer - * @noreturn + * @noreturn */ stock World_GetMaxs(Float:vec[3]) { - + GetEntPropVector(0, Prop_Data, "m_WorldMaxs", vec); }