#if defined _jutils_included #endinput #endif #define _jutils_included #define MODEL_FRANCIS "models/survivors/survivor_biker.mdl" #define MODEL_LOUIS "models/survivors/survivor_manager.mdl" #define MODEL_ZOEY "models/survivors/survivor_teenangst.mdl" #define MODEL_BILL "models/survivors/survivor_namvet.mdl" #define MODEL_NICK "models/survivors/survivor_gambler.mdl" #define MODEL_COACH "models/survivors/survivor_coach.mdl" #define MODEL_ELLIS "models/survivors/survivor_mechanic.mdl" #define MODEL_ROCHELLE "models/survivors/survivor_producer.mdl" #define MODEL_MINIGUN "models/w_models/weapons/w_minigun.mdl" /** Gets a location horizontally X units away from the origin point. Ignores Z-axis. * @noreturn */ stock void GetHorizontalPositionFromOrigin(const float pos[3], const float ang[3], float units, float finalPosition[3]) { float theta = DegToRad(ang[1]); finalPosition[0] = units * Cosine(theta) + pos[0]; finalPosition[1] = units * Sine(theta) + pos[1]; finalPosition[2] = pos[2]; } stock void GetSidePositionFromOrigin(const float pos[3], const float ang[3], float units, float finalPosition[3]) { float theta = DegToRad(ang[1] + 90.0); finalPosition[0] = units * Cosine(theta) + pos[0]; finalPosition[1] = units * Sine(theta) + pos[1]; finalPosition[2] = pos[2]; } stock void GetHorizontalPositionFromClient(int client, float units, float finalPosition[3]) { float pos[3], ang[3]; GetClientEyeAngles(client, ang); GetClientAbsOrigin(client, pos); float theta = DegToRad(ang[1]); pos[0] += units * Cosine(theta); pos[1] += units * Sine(theta); finalPosition = pos; } stock void GetEntityDimensions(int entity, float size[3]) { float maxs[3], mins[3]; GetEntPropVector(entity, Prop_Data, "m_vecMins" , mins); GetEntPropVector(entity, Prop_Data, "m_vecMaxs" , maxs); size[0] = maxs[0] - mins[0]; size[1] = maxs[1] - mins[1]; size[2] = maxs[2] - mins[2]; } // Gets velocity of an entity (ent) toward new origin with speed (fSpeed) - thanks Ryan stock bool GetVelocityToOrigin(int entity, const float destination[3], const float fSpeed, float outVelocity[3]) { float srcOrigin[3]; GetEntPropVector(entity, Prop_Data, "m_vecVelocity", srcOrigin); // Velocity = Distance / Time float fDistance[3]; fDistance[0] = destination[0] - srcOrigin[0]; fDistance[1] = destination[1] - srcOrigin[1]; fDistance[2] = destination[2] - srcOrigin[2]; float fTime = (GetVectorDistance(srcOrigin, destination) / fSpeed); outVelocity[0] = (destination[0] - srcOrigin[0]) / fTime; outVelocity[1] = (destination[1] - srcOrigin[1]) / fTime; outVelocity[2] = (destination[2] - srcOrigin[2]) / fTime; return (outVelocity[0] && outVelocity[1] && outVelocity[2]); } //Credits to Timocop for the stock :D /** * Runs a single line of vscript code. * NOTE: Dont use the "script" console command, it starts a new instance and leaks memory. Use this instead! * * @param sCode The code to run. * @noreturn */ stock void L4D2_RunScript(const char[] sCode, any ...) { static int iScriptLogic = INVALID_ENT_REFERENCE; if(iScriptLogic == INVALID_ENT_REFERENCE || !IsValidEntity(iScriptLogic)) { iScriptLogic = EntIndexToEntRef(CreateEntityByName("logic_script")); if(iScriptLogic == INVALID_ENT_REFERENCE|| !IsValidEntity(iScriptLogic)) SetFailState("Could not create 'logic_script'"); DispatchSpawn(iScriptLogic); } static char sBuffer[512]; VFormat(sBuffer, sizeof(sBuffer), sCode, 2); SetVariantString(sBuffer); AcceptEntityInput(iScriptLogic, "RunScriptCode"); } stock void ShowDelayedHintToAll(const char[] format, any ...) { char buffer[254]; VFormat(buffer, sizeof(buffer), format, 2); static int hintInt = 0; if(hintInt >= 7) { PrintHintTextToAll("%s",buffer); hintInt = 0; } hintInt++; } stock int GetSurvivorId(const char[] str, bool isL4D1 = false) { int possibleNumber = StringToInt(str, 10); if(strlen(str) == 1) { if(possibleNumber <= 7 && possibleNumber >= 0) { return possibleNumber; } }else if(possibleNumber == 0) { int survivorId; char s = CharToLower(str[0]); if(s == 'b') { survivorId = isL4D1 ? 0 : 4; } else if(s == 'z') { survivorId = isL4D1 ? 1 : 5; } else if(s == 'l') { survivorId = isL4D1 ? 2 : 7; } else if(s == 'f') { survivorId = isL4D1 ? 3 : 6; } else if(s == 'n') { survivorId = 0; } else if(s == 'r') { survivorId = 1; } else if(s == 'e') { survivorId = 3; } else if(s == 'c') { survivorId = 2; } return survivorId; } return -1; } stock int GetL4D2SurvivorId(const char str[16]) { int possibleNumber = StringToInt(str, 10); if(strlen(str) == 1) { if(possibleNumber <= 7 && possibleNumber >= 0) { return possibleNumber; } }else if(possibleNumber == 0) { if(StrEqual(str, "nick", false)) return 0; else if(StrEqual(str, "rochelle", false)) return 1; else if(StrEqual(str, "coach", false)) return 2; else if(StrEqual(str, "ellis", false)) return 3; else if(StrEqual(str, "bill", false)) return 0; else if(StrEqual(str, "zoey", false)) return 5; else if(StrEqual(str, "francis", false)) return 3; else if(StrEqual(str, "louis", false)) return 2; } return -1; } stock bool GetSurvivorModel(int character, char[] model, int modelStrSize) { switch(character) { case 0: strcopy(model, modelStrSize, MODEL_NICK); case 1: strcopy(model, modelStrSize, MODEL_ROCHELLE); case 2: strcopy(model, modelStrSize, MODEL_COACH); case 3: strcopy(model, modelStrSize, MODEL_ELLIS); case 4: strcopy(model, modelStrSize, MODEL_BILL); case 5: strcopy(model, modelStrSize, MODEL_ZOEY); case 6: strcopy(model, modelStrSize, MODEL_FRANCIS); case 7: strcopy(model, modelStrSize, MODEL_LOUIS); default: return false; } return true; } stock bool FindSurvivorModel(const char str[16], char[] model, int modelStrSize) { int possibleNumber = StringToInt(str, 10); if(strlen(str) == 1 && possibleNumber <= 7 && possibleNumber >= 0) { switch(possibleNumber) { case 0: strcopy(model, modelStrSize, MODEL_NICK); case 1: strcopy(model, modelStrSize, MODEL_ROCHELLE); case 2: strcopy(model, modelStrSize, MODEL_COACH); case 3: strcopy(model, modelStrSize, MODEL_ELLIS); case 4: strcopy(model, modelStrSize, MODEL_BILL); case 5: strcopy(model, modelStrSize, MODEL_ZOEY); case 6: strcopy(model, modelStrSize, MODEL_FRANCIS); case 7: strcopy(model, modelStrSize, MODEL_LOUIS); default: return false; } return true; }else{ if(possibleNumber == 0) { //try to parse str if(StrEqual(str, "bill", false)) strcopy(model, modelStrSize, MODEL_BILL); else if(StrEqual(str, "zoey", false)) strcopy(model, modelStrSize, MODEL_ZOEY); else if(StrEqual(str, "francis", false)) strcopy(model, modelStrSize, MODEL_FRANCIS); else if(StrEqual(str, "louis", false)) strcopy(model, modelStrSize, MODEL_LOUIS); else if(StrEqual(str, "nick", false)) strcopy(model, modelStrSize, MODEL_NICK); else if(StrEqual(str, "ellis", false)) strcopy(model, modelStrSize, MODEL_ELLIS); else if(StrEqual(str, "rochelle", false)) strcopy(model, modelStrSize, MODEL_ROCHELLE); else if(StrEqual(str, "coach", false)) strcopy(model, modelStrSize, MODEL_COACH); else return false; return true; } } return false; } //returns true if model found stock bool GetSurvivorName(int client, char[] buffer, int length) { char modelName[38]; GetClientModel(client, modelName, sizeof(modelName)); if(StrContains(modelName,"biker",false) > -1) { strcopy(buffer, length, "Francis"); }else if(StrContains(modelName,"teenangst",false) > -1) { strcopy(buffer, length, "Zoey"); }else if(StrContains(modelName,"namvet",false) > -1) { strcopy(buffer, length, "Bill"); }else if(StrContains(modelName,"manager",false) > -1) { strcopy(buffer, length, "Louis"); }else if(StrContains(modelName,"coach",false) > -1) { strcopy(buffer, length, "Coach"); }else if(StrContains(modelName,"producer",false) > -1) { strcopy(buffer, length, "Rochelle"); }else if(StrContains(modelName,"gambler",false) > -1) { strcopy(buffer, length, "Nick"); }else if(StrContains(modelName,"mechanic",false) > -1) { strcopy(buffer, length, "Ellis"); }else{ return false; } return true; } stock int GetSurvivorType(const char[] modelName) { if(StrContains(modelName,"biker",false) > -1) { return 6; }else if(StrContains(modelName,"teenangst",false) > -1) { return 5; }else if(StrContains(modelName,"namvet",false) > -1) { return 4; }else if(StrContains(modelName,"manager",false) > -1) { return 7; }else if(StrContains(modelName,"coach",false) > -1) { return 2; }else if(StrContains(modelName,"producer",false) > -1) { return 1; }else if(StrContains(modelName,"gambler",false) > -1) { return 0; }else if(StrContains(modelName,"mechanic",false) > -1) { return 3; }else{ return false; } } stock bool TraceFilter(int entity, int contentsMask) { if( entity <= MaxClients ) return false; return true; } stock bool GetGround(int client, float vPos[3], float vAng[3]) { GetClientAbsOrigin(client, vPos); vAng = vPos; vAng[2] += 5.0; vPos[2] -= 500.0; Handle trace = TR_TraceRayFilterEx(vAng, vPos, MASK_SOLID, RayType_EndPoint, TraceFilter); if(!TR_DidHit(trace)) { delete trace; return false; } TR_GetEndPosition(vPos, trace); delete trace; GetClientAbsAngles(client, vAng); return true; } stock int GiveClientWeaponLasers(int client, const char[] wpnName) { int entity = GiveClientWeapon(client, wpnName); if(entity != -1) { SetEntProp(entity, Prop_Send, "m_upgradeBitVec", 4); } return entity; } stock int GiveClientWeapon(int client, const char[] wpnName) { static char sTemp[64]; float pos[3]; GetClientAbsOrigin(client, pos); Format(sTemp, sizeof(sTemp), "weapon_%s", wpnName); int entity = CreateEntityByName(sTemp); if( entity != -1 ) { DispatchSpawn(entity); TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR); EquipPlayerWeapon(client, entity); return entity; }else{ return -1; } } stock int GetNearestEntity(int client, char[] classname) { int nearestEntity = -1; float clientVecOrigin[3], entityVecOrigin[3]; //Get the distance between the first entity and client float distance, nearestDistance = -1.0; //Find all the entity and compare the distances int entity = -1; while ((entity = FindEntityByClassname(entity, classname)) != -1) { GetEntPropVector(entity, Prop_Data, "m_vecOrigin", entityVecOrigin); distance = GetVectorDistance(clientVecOrigin, entityVecOrigin, true); if (distance < nearestDistance || nearestDistance == -1.0) { nearestEntity = entity; nearestDistance = distance; } } return nearestEntity; } stock bool IsValidPlayer(int i) { return IsClientConnected(i) && IsClientInGame(i) && IsPlayerAlive(i); } stock bool IsValidTeamPlayer(int i, int team) { return IsValidPlayer(i) && GetClientTeam(i) == team; } stock int GetPrimaryAmmo(int client) { int weapon = GetPlayerWeaponSlot(client, 0); if(weapon > -1) return GetEntProp(weapon, Prop_Send, "m_iClip1"); else return -1; } stock int GetSecondaryAmmo(int client, int weapon) { int activeWpn = GetEntPropEnt(client, Prop_Send, "m_hActiveWeapon"); if(activeWpn == weapon) { int offset = GetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoType"); return GetEntProp(client, Prop_Send, "m_iAmmo", _, offset); } else { return GetEntProp(activeWpn, Prop_Send, "m_iExtraPrimaryAmmo"); } } stock void SetSecondaryAmmo(int client, int weapon, int ammo) { int activeWpn = GetEntPropEnt(client, Prop_Send, "m_hActiveWeapon"); if(activeWpn == weapon) { int offset = GetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoType"); SetEntProp(client, Prop_Send, "m_iAmmo", ammo, _, offset); } else { SetEntProp(activeWpn, Prop_Send, "m_iExtraPrimaryAmmo", ammo); } } stock void CheatCommand(int client, const char[] command, const char[] argument1, const char[] argument2) { int userFlags = GetUserFlagBits(client); SetUserFlagBits(client, ADMFLAG_ROOT); int flags = GetCommandFlags(command); SetCommandFlags(command, flags & ~FCVAR_CHEAT); FakeClientCommand(client, "%s %s %s", command, argument1, argument2); SetCommandFlags(command, flags); SetUserFlagBits(client, userFlags); } //entity abs origin code from here //http://forums.alliedmods.net/showpost.php?s=e5dce96f11b8e938274902a8ad8e75e9&p=885168&postcount=3 stock void GetEntityAbsOrigin(int entity, float origin[3]) { if (entity && IsValidEntity(entity) && (GetEntSendPropOffs(entity, "m_vecOrigin") != -1) && (GetEntSendPropOffs(entity, "m_vecMins") != -1) && (GetEntSendPropOffs(entity, "m_vecMaxs") != -1)) { float mins[3], maxs[3]; GetEntPropVector(entity, Prop_Send, "m_vecOrigin", origin); GetEntPropVector(entity, Prop_Send, "m_vecMins", mins); GetEntPropVector(entity, Prop_Send, "m_vecMaxs", maxs); origin[0] += (mins[0] + maxs[0]) * 0.5; origin[1] += (mins[1] + maxs[1]) * 0.5; origin[2] += (mins[2] + maxs[2]) * 0.5; } } stock bool IsPrimaryWeapon(const char[] wpnName) { return StrContains(wpnName, "rifle") > -1 || StrContains(wpnName, "smg") > -1 || StrContains(wpnName, "weapon_grenade_launcher") > -1 || StrContains(wpnName, "sniper") > -1 || StrContains(wpnName, "shotgun") > -1; } stock int GetClientWeaponEntIndex(int client, int slot) { if(slot >= 0 && slot <= 5) { int wpnRef = GetPlayerWeaponSlot(client, slot); if(wpnRef != -1) { int wpn = EntRefToEntIndex(wpnRef); if(wpn != INVALID_ENT_REFERENCE) { return wpn; }else{ return -1; } }else{ return -1; } }else{ ThrowError("Slot must be a number between 0 and 5"); return -1; } } stock int GetClientSecondaryWeapon(int client) { return GetClientWeaponEntIndex(client, 1); } stock bool GetClientWeaponName(int client, int slot, char[] name, int nameSize) { int wpn = GetClientWeaponEntIndex(client, slot); if(wpn > 0) { GetEntityClassname(wpn, name, nameSize); return true; }else{ return false; } } stock bool GetClientWeaponNameSmart(int client, int slot, char[] name, int nameSize) { int wpn = GetPlayerWeaponSlot(client, slot); if(wpn > 0) { GetEntityClassname(wpn, name, nameSize); if(slot == 1 && StrEqual(name, "weapon_melee")) { GetEntPropString(wpn, Prop_Data, "m_strMapSetScriptName", name, nameSize); } return true; } return false; } stock int GetClientWeaponNameSmart2(int client, int slot, char[] name, int nameSize) { int wpn = GetPlayerWeaponSlot(client, slot); if(wpn > 0) { GetEntityClassname(wpn, name, nameSize); if(slot == 1 && StrEqual(name, "weapon_melee")) { GetEntPropString(wpn, Prop_Data, "m_strMapSetScriptName", name, nameSize); } else { Format(name, nameSize, "%s", name[7]); } return wpn; } return -1; } stock bool DoesClientHaveWeapon(int client, int slot, const char[] name) { char wpn[32]; if(GetClientWeaponName(client, slot, wpn, sizeof(wpn))) { return StrEqual(wpn, name, false); }else{ return false; } } stock bool DoesClientHaveMelee(int client) { int wpnEnt = GetClientSecondaryWeapon(client); if(wpnEnt > -1) { char wpn[16]; GetEdictClassname(wpnEnt, wpn, sizeof(wpn)); return StrEqual(wpn, "weapon_melee"); }else{ return false; } } stock bool IsValidClient(int client, int checkTeam = 0) { int team = checkTeam > 0 ? GetClientTeam(client) : 0; return IsClientConnected(client) && IsClientInGame(client) && IsPlayerAlive(client) && team == checkTeam; } stock bool IsClientInSightRange(int client, int target, float angle = 90.0, float distance = 0.0, bool heightcheck = true, bool negativeangle = false) { if(angle > 360.0 || angle < 0.0) ThrowError("Angle Max : 360 & Min : 0. %d isn't proper angle.", angle); else if(!IsValidClient(client)) ThrowError("Client is not Alive."); else if(!IsValidClient(target)) ThrowError("Target is not Alive."); float clientPos[3], targetPos[3], angleVector[3], targetVector[3], resultAngle, resultDistance; GetClientEyeAngles(client, angleVector); angleVector[0] = angleVector[2] = 0.0; GetAngleVectors(angleVector, angleVector, NULL_VECTOR, NULL_VECTOR); NormalizeVector(angleVector, angleVector); if(negativeangle) NegateVector(angleVector); GetClientAbsOrigin(client, clientPos); GetClientAbsOrigin(target, targetPos); if(heightcheck && distance > 0) resultDistance = GetVectorDistance(clientPos, targetPos); clientPos[2] = targetPos[2] = 0.0; MakeVectorFromPoints(clientPos, targetPos, targetVector); NormalizeVector(targetVector, targetVector); resultAngle = RadToDeg(ArcCosine(GetVectorDotProduct(targetVector, angleVector))); if(resultAngle <= angle/2) { if(distance > 0) { if(!heightcheck) resultDistance = GetVectorDistance(clientPos, targetPos); return distance >= resultDistance; } else return true; } else return false; } /// Checks if entity is in sight of client. Angle is the FOV, distance to be squared stock bool IsEntityInSightRange(int client, int target, float angle = 90.0, float distance = 0.0, bool heightcheck = true, bool negativeangle = false) { if(angle > 360.0 || angle < 0.0) ThrowError("Angle Max : 360 & Min : 0. %d isn't proper angle.", angle); else if(!IsClientConnected(client) || !IsClientInGame(client)) ThrowError("Client is not Alive."); else if(target <= MaxClients || !IsValidEntity(target)) ThrowError("Target is not valid entity."); float clientPos[3], targetPos[3], angleVector[3], targetVector[3], resultAngle, resultDistance; GetClientEyeAngles(client, angleVector); angleVector[0] = angleVector[2] = 0.0; GetAngleVectors(angleVector, angleVector, NULL_VECTOR, NULL_VECTOR); NormalizeVector(angleVector, angleVector); if(negativeangle) NegateVector(angleVector); GetClientAbsOrigin(client, clientPos); GetEntPropVector(target, Prop_Send, "m_vecOrigin", targetPos); if(heightcheck && distance > 0) resultDistance = GetVectorDistance(clientPos, targetPos, true); clientPos[2] = targetPos[2] = 0.0; MakeVectorFromPoints(clientPos, targetPos, targetVector); NormalizeVector(targetVector, targetVector); resultAngle = RadToDeg(ArcCosine(GetVectorDotProduct(targetVector, angleVector))); if(resultAngle <= angle/2) { if(distance > 0) { if(!heightcheck) resultDistance = GetVectorDistance(clientPos, targetPos, true); return distance >= resultDistance; } else return true; } else return false; } stock void PrintChatToAdmins(const char[] format, any ...) { char buffer[254]; VFormat(buffer, sizeof(buffer), format, 2); for(int i = 1; i < MaxClients; i++) { if(IsClientConnected(i) && IsClientInGame(i)) { AdminId admin = GetUserAdmin(i); if(admin != INVALID_ADMIN_ID) { PrintToChat(i, "%s", buffer); } } } PrintToServer("%s", buffer); } #if defined _multicolors_included stock void CPrintChatToAdmins(const char[] format, any ...) { char buffer[254]; VFormat(buffer, sizeof(buffer), format, 2); for(int i = 1; i < MaxClients; i++) { if(IsClientConnected(i) && IsClientInGame(i)) { AdminId admin = GetUserAdmin(i); if(admin != INVALID_ADMIN_ID) { CPrintToChat(i, "%s", buffer); } } } CPrintToServer("%s", buffer); } #endif stock bool IsValidAdmin(int client, const char[] flags) { int ibFlags = ReadFlagString(flags); if ((GetUserFlagBits(client) & ibFlags) == ibFlags) { return true; }else if (GetUserFlagBits(client) & ADMFLAG_ROOT) { return true; } return false; } stock float GetNearestEntityDistance(int originEntity, char[] classname) { float compareVec[3], entityVecOrigin[3]; GetEntPropVector(originEntity, Prop_Send, "m_vecOrigin", compareVec); //Get the distance between the first entity and client float distance, nearestDistance = -1.0; int entity = -1, closest; while ((entity = FindEntityByClassname(entity, classname)) != -1) { GetEntPropVector(entity, Prop_Send, "m_vecOrigin", entityVecOrigin); distance = GetVectorDistance(compareVec, entityVecOrigin); // PrintDebug(DEBUG_SPAWNLOGIC, "Comparing %s (id %d) (%.2f,%.2f,%.2f) distance to entity %d (%.2f,%.2f,%.2f) is %.4f", classname, entity, entityVecOrigin[0], entityVecOrigin[1], entityVecOrigin[2], originEntity, compareVec[0], compareVec[1], compareVec[2], distance); if (distance < nearestDistance || nearestDistance == -1.0) { nearestDistance = distance; closest = entity; } } return closest > 0 ? nearestDistance : -1.0; } stock int FindNearestEntityInRange(int originEntity, char[] classname, float range) { float compareVec[3], entityVecOrigin[3]; GetEntPropVector(originEntity, Prop_Send, "m_vecOrigin", compareVec); //Get the distance between the first entity and client float distance, nearestDistance = -1.0; int entity = -1, closest = -1; while ((entity = FindEntityByClassname(entity, classname)) != -1) { GetEntPropVector(entity, Prop_Send, "m_vecOrigin", entityVecOrigin); distance = GetVectorDistance(compareVec, entityVecOrigin); if (distance <= range && (distance < nearestDistance || nearestDistance == -1.0)) { // PrintDebug(DEBUG_SPAWNLOGIC, "Comparing %s (id %d) (%.2f,%.2f,%.2f) distance to entity %d (%.2f,%.2f,%.2f) is %.4f", classname, entity, entityVecOrigin[0], entityVecOrigin[1], entityVecOrigin[2], originEntity, compareVec[0], compareVec[1], compareVec[2], distance); nearestDistance = distance; closest = entity; } } return closest; } stock void MakeEntityGlow(int entity, const int color[3], float distance = 1500.0) { SetEntProp(entity, Prop_Send, "m_iGlowType", 3); SetEntProp(entity, Prop_Send, "m_nGlowRange", distance); SetEntProp(entity, Prop_Send, "m_glowColorOverride", color[0] + (color[1] * 256) + (color[2] * 65536)); } //Unless I'm dumb, this does not exist stock void StringToLower(char[] str) { int len = strlen(str); for(int i = 0; i < len; i++) { str[i] = CharToLower(str[i]); } } stock void StringToUpper(char[] str) { int len = strlen(str); for(int i = 0; i < len; i++) { str[i] = CharToUpper(str[i]); } } stock int GetRealClient(int bot) { if(!IsFakeClient(bot)) return -1; static char netclass[16]; GetEntityNetClass(bot, netclass, sizeof(netclass)); if(StrEqual(netclass, "SurvivorBot")) { int user = GetEntProp(bot, Prop_Send, "m_humanSpectatorUserID"); if(user > 0) return GetClientOfUserId(user); } return -1; } stock int FindIdleBot(int client) { for(int i = 1; i <= MaxClients; i++ ) { if(IsClientConnected(i) && IsClientInGame(i) && HasEntProp(i, Prop_Send, "m_humanSpectatorUserID")) { int realPlayer = GetClientOfUserId(GetEntProp(i, Prop_Send, "m_humanSpectatorUserID")); if(realPlayer == client) { return i; } } } return -1; } stock void SetParent(int child, int parent) { SetVariantString("!activator"); AcceptEntityInput(child, "SetParent", parent); } stock void SetParentAttachment(int child, const char[] attachment, bool withOffset = false) { SetVariantString(attachment); if(withOffset) AcceptEntityInput(child, "SetParentAttachmentMaintainOffset"); else AcceptEntityInput(child, "SetParentAttachment"); } stock void ClearParent(int child) { AcceptEntityInput(child, "ClearParent"); } stock void GetForwardVector(float vPos[3], float vAng[3], float vReturn[3], float fDistance) { float vDir[3]; GetAngleVectors(vAng, vDir, NULL_VECTOR, NULL_VECTOR); ScaleVector(vDir, fDistance); AddVectors(vPos, vDir, vReturn); } stock void GetDirectionVector(float pos1[3], float angle[3], float rVec[3], float distance, float force) { float endPos[3]; GetForwardVector(pos1, angle, endPos, distance); MakeVectorFromPoints(pos1, endPos, rVec); NormalizeVector(rVec, rVec); ScaleVector(rVec, force); } // Taken from https://gist.github.com/Aeldrion/48c82912f632eec4c8b9da7394b89c5d stock void HSVToRGB(const float vec[3], float out[3]) { // Translates HSV color to RGB color // H: 0.0 - 360.0, S: 0.0 - 100.0, V: 0.0 - 100.0 // R, G, B: 0.0 - 1.0 float hue = vec[0]; float saturation = vec[1]; float value = vec[2]; float c = (value / 100.0) * (saturation / 100.0); float x = c * (1.0 - FloatAbs(float(RoundToFloor(hue / 60) % 2) - 1)); float m = (value / 100.0) - c; if (hue >= 0 && hue < 60.0) { out[0] = c; out[1] = x; out[2] = 0.0; } else if (hue >= 60.0 && hue < 120.0) { out[0] = x; out[1] = c; out[2] = 0.0; } else if (hue >= 120.0 && hue < 180.0) { out[0] = 0.0; out[1] = c; out[2] = x; } else if (hue >= 180.0 && hue < 240.0) { out[0] = 0.0; out[1] = x; out[2] = c; } else if (hue >= 240.0 && hue < 300.0) { out[0] = x; out[1] = 0.0; out[2] = c; } else if (hue >= 300.0 && hue < 360.0) { out[0] = c; out[1] = 0.0; out[2] = x; } out[0] += m; out[1] += m; out[2] += m; out[0] * 255.0; out[1] * 255.0; out[2] * 255.0; } stock void HSVToRGBInt(const float vec[3], int out[3]) { // Don't initialize memory, just use the existing memory as int out[3], just tell it that is a float HSVToRGB(vec, view_as(out)); // Convert float to int: out[0] = RoundToFloor(view_as(out[0])); out[1] = RoundToFloor(view_as(out[1])); out[2] = RoundToFloor(view_as(out[2])); } stock bool GetCursorLocation(int client, float outPos[3]) { float angle[3]; GetClientEyePosition(client, outPos); GetClientEyeAngles(client, angle); TR_TraceRayFilter(outPos, angle, MASK_SOLID, RayType_Infinite, Filter_IgnorePlayer, client); if(TR_DidHit()) { TR_GetEndPosition(outPos); return true; } else { return false; } } bool Filter_IgnorePlayer(int entity, int mask, int data) { return entity > 0 && entity != data; } bool Filter_World(int entity, int mask, int data) { return entity == 0; } // Gets a position from where the cursor is upto distance away (basically <= distance, going against walls) stock bool GetCursorLimited(int client, float distance, float endPos[3], TraceEntityFilter filter) { if (client > 0 && client <= MaxClients && IsClientInGame(client)) { float clientEye[3], clientAngle[3], direction[3]; GetClientEyePosition(client, clientEye); GetClientEyeAngles(client, clientAngle); GetAngleVectors(clientAngle, direction, NULL_VECTOR, NULL_VECTOR); ScaleVector(direction, distance); AddVectors(clientEye, direction, endPos); TR_TraceRayFilter(clientEye, endPos, MASK_OPAQUE, RayType_EndPoint, filter, client); if (TR_DidHit(INVALID_HANDLE)) { TR_GetEndPosition(endPos); } return true; } return false; } stock void SetWeaponDelay(int client, float delay) { int pWeapon = GetEntPropEnt(client, Prop_Send, "m_hActiveWeapon"); if (pWeapon > -1) { SetEntPropFloat(pWeapon, Prop_Send, "m_flNextPrimaryAttack", GetGameTime() + delay); SetEntPropFloat(pWeapon, Prop_Send, "m_flNextSecondaryAttack", GetGameTime() + delay); } } // Sends client a menu selecting a player, see COMMAND_FILTER_* for flags, idPrefix is appended to menu item's id stock void QueryPlayer(int client, MenuHandler handler, int flags = COMMAND_FILTER_NO_IMMUNITY, const char[] title = "Select a player", const char[] idPrefix = "", int time = 0) { Menu menu = new Menu(handler); menu.SetTitle(title, client); char id[32], display[32]; for(int i = 1; i <= MaxClients; i++) { if(IsClientConnected(i) && (IsClientInGame(i) || flags & COMMAND_FILTER_CONNECTED)) { if(flags & COMMAND_FILTER_NO_BOTS && IsFakeClient(i)) continue; if(flags & COMMAND_FILTER_ALIVE && !IsPlayerAlive(i)) continue; if(flags & COMMAND_FILTER_DEAD && IsPlayerAlive(i)) continue; if(~flags & COMMAND_FILTER_NO_IMMUNITY && !CanUserTarget(client, i)) continue; Format(id, sizeof(id), "%s%d", idPrefix, GetClientUserId(i)); if(IsFakeClient(i)) { int realPlayer = GetRealClient(i); if(realPlayer > 0) { if(IsPlayerAlive(i)) { Format(display, sizeof(display), "%N (Idle)", realPlayer); } else { Format(display, sizeof(display), "%N (Idle)(Dead)", realPlayer); } } else if(IsPlayerAlive(i)) { Format(display, sizeof(display), "%N", i); } else { Format(display, sizeof(display), "%N (dead)", i); } } else if(IsPlayerAlive(i)) { Format(display, sizeof(display), "%N", i); } else { Format(display, sizeof(display), "%N (dead)", i); } menu.AddItem(id, display); } } menu.Display(client, time); } stock bool IsNearGround(int ref, float distFromGround = 15.0) { static float sPos[3], ePos[3]; GetEntPropVector(ref, Prop_Send, "m_vecOrigin", sPos); ePos[0] = sPos[0]; ePos[1] = sPos[1]; ePos[2] = sPos[2] -= 15.0; TR_TraceRayFilter(sPos, ePos, MASK_SOLID, RayType_EndPoint, Filter_IgnorePlayer, ref); if(TR_DidHit()) { return true; } return false; } stock bool IsAreaClear(const float pos[3], const float ang[3], const float minBound[3], const float maxBound[3]) { TR_TraceHullFilter(pos, pos, minBound, maxBound, MASK_SOLID, Filter_World); if(TR_DidHit()) { return false; } return true; } stock Action Timer_KillEntity(Handle h, int entity) { RemoveEntity(entity); return Plugin_Handled; } stock int GetSinglePlayer(int client, const char[] input, int flags = 0) { flags |= COMMAND_FILTER_NO_MULTI; char buf[2]; int target_list[1], target_count; bool tn_is_ml; if ((target_count = ProcessTargetString( input, client, target_list, 1, flags, buf, 2, tn_is_ml)) <= 0 ) { ReplyToTargetError(client, target_count); return -1; } return target_list[0]; } #if defined _l4dh_included static int _glowColor[3] = { 255, 255, 255 }; stock void GlowPoint(const float pos[3], float lifetime = 5.0) { PrecacheModel("models/props_fortifications/orange_cone001_reference.mdl"); int entity = CreateEntityByName("prop_dynamic"); DispatchKeyValue(entity, "disableshadows", "1"); DispatchKeyValue(entity, "model", "models/props_fortifications/orange_cone001_reference.mdl"); TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR); DispatchSpawn(entity); L4D2_SetEntityGlow(entity, L4D2Glow_Constant, 10000, 0, _glowColor, false); CreateTimer(lifetime, Timer_KillEntity, entity); } stock void GlowEntity(int entity, float lifetime = 10.0, int glowColor[3] = _glowColor) { L4D2_SetEntityGlow(entity, L4D2Glow_Constant, 10000, 0, glowColor, false); if(lifetime > 0.0) CreateTimer(lifetime, Timer_ClearGlow, EntIndexToEntRef(entity)); } Action Timer_ClearGlow(Handle h, int ref) { L4D2_RemoveEntityGlow(ref); return Plugin_Handled; } #endif stock bool CompareVector(const float a[3], const float b[3], float delta) { return a[0] < b[0] + delta && a[0] > b[0] - delta && a[1] < b[1] + delta && a[1] > b[1] - delta && a[2] < b[2] + delta && a[2] > b[2] - delta } stock void CalculateWorldPosition(int entity, float pos[3]) { float mins[3], maxs[3]; GetEntPropVector(entity, Prop_Send, "m_vecOrigin", pos); GetEntPropVector(entity, Prop_Send, "m_vecMins", mins); GetEntPropVector(entity, Prop_Send, "m_vecMaxs", maxs); pos[0] = pos[0] + (mins[0] + maxs[0]) * 0.5; pos[1] = pos[1] + (mins[1] + maxs[1]) * 0.5; pos[2] = pos[2] + (mins[2] + maxs[2]) * 0.5; } #if defined _l4dh_included /// Displays either: Username, Username (AFK), Username (Dead), Userame (AFK/Dead) stock void GetMenuDisplayName(int client, char[] display, int maxlen) { int realPlayer = L4D_GetIdlePlayerOfBot(client); // Incase player is idle, grab their bot instead of them if(realPlayer > 0 && IsClientConnected(realPlayer)) { if(IsPlayerAlive(client)) Format(display, maxlen, "%N (AFK)", realPlayer); else Format(display, maxlen, "%N (AFK/Dead)", realPlayer); } else if(!IsPlayerAlive(client)) Format(display, maxlen, "%N (Dead)", client); else { GetClientName(client, display, maxlen); } } #endif stock int MathMax(int a, int b) { return a > b ? a : b; } stock int MathMin(int a, int b) { return a < b ? a : b; }