Don't think I've seen this done yet. We have legs and ragdolls and pretty much everything else from L4D1 at this point.
In L4D2, the hunter and the tank only go for downed survivors if they are vomitted or if they are directly in front of them. Otherwise they ignore them. This was changed from their behavior in L4D1.
In L4D1, the hunter and the tank would prioritize incapped survivors at all times, regardless of vomit or if they were directly in front of them. What im looking for is a return of these features. The tank would continue to pound downed survivors to kill them and then go after other survivors and the hunters would pounce incapped survivors to finish them off and then go after other survivors.
With detours and whatnot, I'm thinking this could be doable now.
This is doable now that Left 4 Downtown 2 has that nifty "L4D2_OnChooseVictim" forward.
If only left 4 downtown 2 actually worked and didn't have 20 different versions that nobody knows in what version of sourcemod they are supposed to run.
If only left 4 downtown 2 actually worked and didn't have 20 different versions that nobody knows in what version of sourcemod they are supposed to run.
The one I'm currently using is Accelerator's latest version and a different gamedata with all the working signatures for Windows.
Anyways, here you go Sev.
I think this should restore that behavior you're looking for:
PHP Code:
#include <left4downtown>
int iLastVictim[MAXPLAYERS+1]; // We need this to record the SI's last target before it was changed due to someone being vomited.
public Action L4D2_OnChooseVictim(int specialInfected, int &curTarget) { if (!IsInfected(specialInfected) || !IsFakeClient(specialInfected)) { return Plugin_Continue; // Of course, let's not forget the trusty old validity check first. }
/* Uncomment the lines after this in case you prefer that the SI don't target each other after */ /* being biled. */
/* This also makes them target the victim they were supposed to be attacking earlier. */ /* If there wasn't any or their previous target is already dead, we search for the */ /* closest survivor to them. */ // if (IsInfected(curTarget)) // { // /* Looking at the source code after wondering why returning Plugin_Changed had no effect */ // /* at all even though it says that in the include file to change the values, it turns out that */ // /* Plugin_Handled was the answer all this time. */ // if (!IsAliveSurvivor(iLastVictim[specialInfected]) // { // curTarget = GetNearestSurvivor(specialInfected); // } // else // { // curTarget = iLastVictim[specialInfected]; // } // return Plugin_Handled; // } // else // { int iClass = GetEntProp(specialInfected, Prop_Send, "m_zombieClass"); if (iClass != 3 && iClass != 8) { return Plugin_Continue; // Only find Hunters and Tanks. }
if (IsSurvivor(curTarget)) { if (IsAliveSurvivor(iLastVictim[specialInfected])) { // This here is a bit tricky since there will be a scenario where the target is running away // from the tank and there's a chance that (an) incapacitated survivor(s) will be in the // way. In order to give the full experience of restoring the usual behavior from L4D1, we // must not skip them. int iNearbyTarget = GetNearbySurvivor(specialInfected, curTarget); if (IsAliveSurvivor(iNearbyTarget) && GetEntProp(iNearbyTarget, Prop_Send, "m_isIncapacitated", 1)) { // Presto change-o! iLastVictim[specialInfected] = iNearbyTarget;
curTarget = iNearbyTarget; return Plugin_Handled; } else { if (iLastVictim[specialInfected] == curTarget || !GetEntProp(iLastVictim[specialInfected], Prop_Send, "m_isIncapacitated", 1)) { return Plugin_Continue; // Target remain unchanged or let the game decide. }
// Make the Hunters and Tanks focus on the incapacitated survivors first, no matter // if they kill each other. curTarget = iLastVictim[specialInfected]; return Plugin_Handled; } else { // Remember the current target for later. iLastVictim[specialInfected] = curTarget; } } /* Uncomment the lines below this if you want them to still hunt for potential victims even */ /* when all survivors are down. Useful for servers with the director applying death checks */ /* after everyone is dead. */ // else // { // int iNearbyTarget = GetNearestSurvivor(specialInfected); // if (iNearbyTarget < 1) // { // return Plugin_Continue; // No more alive survivors left, the round is about to end. // } // // // curTarget = iNearbyTarget; // return Plugin_Handled; // } // } // Uncomment this only if you want to apply all of the above.
return Plugin_Continue; }
int GetNearestSurvivor(int client, int iExclude = 0) { int iFound = 0; float fPos[2][3], fClosestDist;
That would still be overridden by the default behavior in L4D2 cuz how a bot SI decides its target is determined every frame. That also explains why they change targets whenever someone is vomited.
That could work but it might produce some other unexpected results like the SI moving back and forth between the vomited survivors and the one we're forcing it to attack.
Off-topic: I was able to use the Charger Chestbump Patch plugin for Windows with the use of the wildcarded signature for HandleCustomCollision since the one in the gamedata I have for L4DT2 to work is the original.