diff --git a/addons/sourcemod/configs/szf/classes.cfg b/addons/sourcemod/configs/szf/classes.cfg index 0d0da28f..27b88758 100644 --- a/addons/sourcemod/configs/szf/classes.cfg +++ b/addons/sourcemod/configs/szf/classes.cfg @@ -4,6 +4,7 @@ // enable Player can select and play that class. // health Max health to add/remove. // regen Health regenerated every second. + // speed Speed in hu/s to add/remove //Survivor // ammo Primary ammo gained on a kill or assist. @@ -46,6 +47,7 @@ "scout" { + "speed" "-30" "ammo" "2" "menu" "Menu_ClassesSurvivorsScout" } @@ -326,6 +328,7 @@ "viewmodel" "models/kirillian/weapons/hank_viewmodel_v2f.mdl" "viewmodel_anim" "1" + "speed" "230" // double its movement speed "ragecooldown" "5" "callback_spawn" "Infected_OnTankSpawn" "callback_rage" "Infected_DoTankThrow" @@ -336,7 +339,7 @@ "weapon" { "index" "5" // Fists - "attrib" "107 ; 2.0 ; 236 ; 1.0 ; 329 ; 0.0 ; 405 ; 0.0" // move speed bonus, weapon blocks healing, airblast immunity, vertical airblast immunity + "attrib" "236 ; 1.0 ; 329 ; 0.0 ; 405 ; 0.0" // weapon blocks healing, airblast immunity, vertical airblast immunity "logname" "infection_heavy" "iconname" "infection_heavy" } diff --git a/addons/sourcemod/configs/szf/weapons.cfg b/addons/sourcemod/configs/szf/weapons.cfg index 39bfaefe..f078c388 100644 --- a/addons/sourcemod/configs/szf/weapons.cfg +++ b/addons/sourcemod/configs/szf/weapons.cfg @@ -56,7 +56,7 @@ "220" // Shortstop { - "rarity" "rare" + "rarity" "uncommon" "model" "models/weapons/c_models/c_shortstop/c_shortstop.mdl" } @@ -68,7 +68,7 @@ "772" // Baby Face's Blaster { - "rarity" "uncommon" + "rarity" "rare" "model" "models/weapons/c_models/c_pep_scattergun.mdl" } diff --git a/addons/sourcemod/scripting/superzombiefortress.sp b/addons/sourcemod/scripting/superzombiefortress.sp index 2e0aaf11..7d15a8f6 100644 --- a/addons/sourcemod/scripting/superzombiefortress.sp +++ b/addons/sourcemod/scripting/superzombiefortress.sp @@ -19,7 +19,7 @@ #include "include/superzombiefortress.inc" -#define PLUGIN_VERSION "4.7.2" +#define PLUGIN_VERSION "4.7.3" #define PLUGIN_VERSION_REVISION "manual" #define MAX_CONTROL_POINTS 8 @@ -193,6 +193,7 @@ enum struct ClientClasses bool bEnabled; int iHealth; int iRegen; + float flSpeed; //Survivor int iAmmo; @@ -1929,7 +1930,7 @@ ArrayList FastRespawnNearby(float flMinDistance, float flMaxDistance, int iForce g_aFastRespawn.GetArray(i, vecPosOrigin); bool bAllow = true; - bool bDistance = false; + int iDistanceCount = 0; //Check if survivors can see it for (int iClient = 1; iClient <= MaxClients; iClient++) @@ -1947,14 +1948,15 @@ ArrayList FastRespawnNearby(float flMinDistance, float flMaxDistance, int iForce vecPosClient[2] += (vecPosClient[2] - vecPosOrigin[2]) * 4.0; float flDistance = GetVectorDistance(vecPosClient, vecPosOrigin); - if (flDistance < flMinDistance) + if (flMinDistance < flDistance) { + // Never allow spawn if too close to any clients bAllow = false; break; } else if (flDistance <= flMaxDistance) { - bDistance = true; + iDistanceCount++; } if (!iForceClient) @@ -1975,7 +1977,11 @@ ArrayList FastRespawnNearby(float flMinDistance, float flMaxDistance, int iForce break; } - if (bAllow && bDistance) + if (!bAllow) + continue; + + // Require to be nearby atleast 33% of survivors + if (iForceClient || float(iDistanceCount) >= float(GetSurvivorCount()) * 0.33) aTombola.PushArray(vecPosOrigin); } @@ -2038,30 +2044,16 @@ void FastRespawnDataCollect() { float vecPos[3]; g_aFastRespawn.GetArray(i, vecPos); - - bool bDelete = true; - for (int iClient = 1; iClient <= MaxClients; iClient++) - { - if (!IsValidLivingClient(iClient)) - continue; - - if (DistanceFromEntityToPoint(iClient, vecPos) > 1250.0) - continue; - - bDelete = false; - break; - } - - if (bDelete) + if (!IsValidFastRespawnSpot(vecPos)) g_aFastRespawn.Erase(i); } for (int iClient = 1; iClient <= MaxClients; iClient++) { - if (!IsValidLivingClient(iClient) || GetEntityFlags(iClient) & FL_DUCKING || !(GetEntityFlags(iClient) & FL_ONGROUND)) + if (!IsValidLivingClient(iClient) || !(GetEntityFlags(iClient) & FL_ONGROUND)) continue; - ArrayList aPos = FastRespawnNearby(0.0, 100.0, iClient); + ArrayList aPos = FastRespawnNearby(0.0, 50.0, iClient); if (aPos) { delete aPos; @@ -2070,11 +2062,37 @@ void FastRespawnDataCollect() { float vecPos[3]; GetClientAbsOrigin(iClient, vecPos); - g_aFastRespawn.PushArray(vecPos); + if (IsValidFastRespawnSpot(vecPos)) + g_aFastRespawn.PushArray(vecPos); } } } +bool IsValidFastRespawnSpot(const float vecPos[3]) +{ + // Is spot not stuck in something, like func_respawnroomvisualizer? + Handle hTrace = TR_TraceHullFilterEx(vecPos, vecPos, { -24.0, -24.0, 0.0 }, { 24.0, 24.0, 83.0 }, MASK_PLAYERSOLID, Trace_DontHitClients); + bool bHit = TR_DidHit(hTrace); + delete hTrace; + + if (bHit) + return false; + + // Is any survivors nearby it? + for (int iClient = 1; iClient <= MaxClients; iClient++) + { + if (!IsValidLivingSurvivor(iClient)) + continue; + + if (DistanceFromEntityToPoint(iClient, vecPos) > 1250.0) + continue; + + return true; + } + + return false; +} + void HandleSurvivorLoadout(int iClient) { if (!IsValidClient(iClient) || !IsPlayerAlive(iClient)) diff --git a/addons/sourcemod/scripting/szf/config.sp b/addons/sourcemod/scripting/szf/config.sp index e458d578..2c6f5e0e 100644 --- a/addons/sourcemod/scripting/szf/config.sp +++ b/addons/sourcemod/scripting/szf/config.sp @@ -263,6 +263,7 @@ bool Config_LoadClassesSection(KeyValues kv, ClientClasses classes) //Survivor, Zombie and Infected classes.bEnabled = !!kv.GetNum("enable", classes.bEnabled); classes.iRegen = kv.GetNum("regen", classes.iRegen); + classes.flSpeed = kv.GetFloat("speed", classes.flSpeed); //Survivor classes.iAmmo = kv.GetNum("ammo", classes.iAmmo); @@ -606,8 +607,14 @@ void Config_GetRandomDebris(Debris debris) delete aList; } -bool Config_GetDebrisFromModel(const char[] sModel, Debris debris) +bool Config_GetDebrisFromEntity(int iEntity, Debris debris) { + if (!IsClassname(iEntity, "prop_physics")) + return false; + + char sModel[256]; + GetEntityModel(iEntity, sModel, sizeof(sModel)); + int iLength = g_aConfigDebris.Length; for (int i = 0; i < iLength; i++) { diff --git a/addons/sourcemod/scripting/szf/dhook.sp b/addons/sourcemod/scripting/szf/dhook.sp index 031ad8cf..c70ababf 100644 --- a/addons/sourcemod/scripting/szf/dhook.sp +++ b/addons/sourcemod/scripting/szf/dhook.sp @@ -147,6 +147,8 @@ public MRESReturn DHook_CalculateMaxSpeedPost(int iClient, DHookReturn hReturn) { float flSpeed = hReturn.Value; + flSpeed += g_ClientClasses[iClient].flSpeed; + if (IsZombie(iClient)) { if (g_nInfected[iClient] == Infected_None) diff --git a/addons/sourcemod/scripting/szf/event.sp b/addons/sourcemod/scripting/szf/event.sp index a146ae55..ae2e71a7 100644 --- a/addons/sourcemod/scripting/szf/event.sp +++ b/addons/sourcemod/scripting/szf/event.sp @@ -266,14 +266,11 @@ public Action Event_PlayerDeath(Event event, const char[] name, bool dontBroadca if (IsValidZombie(iKillers[0]) && g_nInfected[iKillers[0]] == Infected_Spitter && event.GetInt("customkill") == TF_CUSTOM_BLEEDING) event.SetString("weapon", "infection_acid_puddle"); - if (iInflictor != INVALID_ENT_REFERENCE && IsClassname(iInflictor, "prop_physics")) + if (iInflictor != INVALID_ENT_REFERENCE) { // Could be a tank thorwing debris to set kill icon - char sModel[256]; - GetEntityModel(iInflictor, sModel, sizeof(sModel)); - Debris debris; - if (Config_GetDebrisFromModel(sModel, debris)) + if (Config_GetDebrisFromEntity(iInflictor, debris)) event.SetString("weapon", debris.sIconName); } diff --git a/addons/sourcemod/scripting/szf/infected.sp b/addons/sourcemod/scripting/szf/infected.sp index 0c3769af..9485ecc6 100644 --- a/addons/sourcemod/scripting/szf/infected.sp +++ b/addons/sourcemod/scripting/szf/infected.sp @@ -194,8 +194,6 @@ public void Infected_DoTankThrow(int iClient) DispatchSpawn(iDebris); - SetEntPropFloat(iDebris, Prop_Data, "m_impactEnergyScale", 0.0); //After DispatchSpawn, otherwise 1 would be set - g_iTankDebris[iClient] = EntIndexToEntRef(iDebris); CreateTimer(flThrow, Infected_DebrisTimer, GetClientSerial(iClient)); @@ -313,15 +311,18 @@ void Infected_DebrisFrameFadeOut(int iDebris) public Action Infected_DebrisStartTouch(int iDebris, int iToucher) { + if (iToucher <= 0 || iToucher > MaxClients) + return Plugin_Continue; + int iClient = GetEntPropEnt(iDebris, Prop_Send, "m_hOwnerEntity"); float vecVelocity[3]; SDKCall_GetVelocity(iDebris, vecVelocity); float flSpeed = GetVectorLength(vecVelocity); + if (flSpeed < 100.0) + return Plugin_Continue; - if (0 < iToucher <= MaxClients && flSpeed >= 100.0) - SDKHooks_TakeDamage(iToucher, iDebris, iClient, flSpeed / 4.0); - + SDKHooks_TakeDamage(iToucher, iDebris, iClient, flSpeed / 4.0); return Plugin_Continue; } diff --git a/addons/sourcemod/scripting/szf/sdkhook.sp b/addons/sourcemod/scripting/szf/sdkhook.sp index ce97af6d..b3acd9b7 100644 --- a/addons/sourcemod/scripting/szf/sdkhook.sp +++ b/addons/sourcemod/scripting/szf/sdkhook.sp @@ -102,6 +102,10 @@ public Action Client_OnTakeDamage(int iVictim, int &iAttacker, int &iInflicter, if (!CanRecieveDamage(iVictim)) return Plugin_Continue; + Debris debris; + if (Config_GetDebrisFromEntity(iInflicter, debris) && GetEntPropEnt(iInflicter, Prop_Send, "m_hOwnerEntity") != iAttacker) + return Plugin_Stop; // Prevent TF2 game allowing debris to damage victim, we want to handle our own damages + bool bChanged = false; if (g_ClientClasses[iVictim].callback_damage != INVALID_FUNCTION) diff --git a/addons/sourcemod/scripting/szf/stocks.sp b/addons/sourcemod/scripting/szf/stocks.sp index 01588ec0..0eab3ddc 100644 --- a/addons/sourcemod/scripting/szf/stocks.sp +++ b/addons/sourcemod/scripting/szf/stocks.sp @@ -1056,6 +1056,11 @@ bool Trace_DontHitEntity(int iEntity, int iMask, any iData) return true; } +bool Trace_DontHitClients(int iEntity, int iMask, any iData) +{ + return iEntity <= 0 || iEntity > MaxClients; +} + bool Trace_DontHitTeammates(int iEntity, int iMask, any iData) { if (iEntity <= 0 || iEntity > MaxClients)