Re: [L4D & L4D2] Target Override (2.1) [23-Mar-2020]
Quote:
Originally Posted by sorallll
(Post 2688262)
L 03/24/2020 - 07:38:14: [SM] MEMORY LEAK DETECTED IN PLUGIN (file "optional/coop/l4d_target_override.smx")
L 03/24/2020 - 07:38:14: [SM] Unloading plugin to free 31530 handles.
L 03/24/2020 - 07:38:14: [SM] Contact the author(s) of this plugin to correct this error.
L 03/24/2020 - 07:38:14: --------------------------------------------------------------------------
L 03/24/2020 - 07:38:14: Type CellArray | Count 31527
L 03/24/2020 - 07:38:14: Type HookSetup | Count 1
L 03/24/2020 - 07:38:14: Type HookParams | Count 1
L 03/24/2020 - 07:38:14: Type HookReturn | Count 1
L 03/24/2020 - 07:38:14: -- Approximately 3652812 bytes of memory are in use by (31530) Handles.
L 03/24/2020 - 07:38:14: [SM] Exception reported: Memory leak
L 03/24/2020 - 07:38:14: [SM] Blaming: optional/coop/l4d_target_override.smx
L 03/24/2020 - 07:38:14: [SM] Call stack trace:
L 03/24/2020 - 07:38:14: [SM] [0] ArrayList.ArrayList
L 03/24/2020 - 07:38:14: [SM] [1] Line 699, l4d_target_override.sp::ChooseVictim
L 03/24/2020 - 07:45:07: Error log file session closed.
|
From quick skim don't really understand the code much but the error should fix after you put
Just before the function returns.
Here did it below replace the whole function with this one.
PHP Code:
public MRESReturn ChooseVictim(int attacker, Handle hReturn)
{
#if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
StartProfiling(g_Prof);
#endif
#if DEBUG_BENCHMARK == 3
PrintToServer("");
PrintToServer("");
PrintToServer("ENTRY %d (%N)", attacker, attacker);
#endif
// =========================
// VALIDATE SPECIAL ALLOWED CHANGE TARGET
// =========================
// 1=Smoker, 2=Boomer, 3=Hunter, 4=Spitter, 5=Jockey, 6=Charger, 5 (L4D1) / 8 (L4D2)=Tank
int class = GetEntProp(attacker, Prop_Send, "m_zombieClass");
if( class == (g_bLeft4Dead2 ? 8 : 5) ) class -= 1;
if( g_iCvarSpecials & (1 << class - 1) == 0 )
{
#if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
StopProfiling(g_Prof);
float speed = GetProfilerTime(g_Prof);
if( speed < g_fBenchMin ) g_fBenchMin = speed;
if( speed > g_fBenchMax ) g_fBenchMax = speed;
g_fBenchAvg += speed;
g_iBenchTicks++;
#endif
#if DEBUG_BENCHMARK == 2
PrintToServer("ChooseVictim End 1 in %f (Min %f. Avg %f. Max %f)", speed, g_fBenchMin, g_fBenchAvg / g_iBenchTicks, g_fBenchMax);
#endif
return MRES_Ignored;
}
// Change tank class for use as index
if( class == (g_bLeft4Dead2 ? 7 : 4) )
{
class = 0;
}
// =========================
// VALIDATE OLD TARGET, WAIT
// =========================
int newVictim;
int lastVictim = g_iLastVictim[attacker];
if( lastVictim )
{
// Player disconnected or player dead, otherwise validate last selected order still applies
if( IsClientInGame(lastVictim) == true && IsPlayerAlive(lastVictim) )
{
#if DEBUG_BENCHMARK == 3
PrintToServer("=== Test Last: Order: %d. newVictim %d (%N)", g_iLastOrders[attacker], lastVictim, lastVictim);
#endif
newVictim = OrderTest(attacker, lastVictim, GetClientTeam(lastVictim), g_iLastOrders[attacker]);
#if DEBUG_BENCHMARK == 3
PrintToServer("=== Test Last: newVictim %d (%N)", lastVictim, lastVictim);
#endif
}
// Not reached delay time
if( newVictim && GetGameTime() <= g_fLastSwitch[attacker] )
{
#if DEBUG_BENCHMARK == 3
PrintToServer("=== Test Last: wait delay.");
#endif
// CONTINUE OVERRIDE LAST
DHookSetReturn(hReturn, newVictim);
return MRES_Supercede;
}
else
{
#if DEBUG_BENCHMARK == 3
PrintToServer("=== Test Last: wait reset.");
#endif
g_iLastOrders[attacker] = 0;
g_iLastVictim[attacker] = 0;
g_fLastSwitch[attacker] = 0.0;
}
}
// =========================
// FIND NEAREST SURVIVORS
// =========================
// Visible near
float vPos[3];
int targets[MAXPLAYERS+1];
ArrayList aTargets = new ArrayList(3);
GetClientEyePosition(attacker, vPos);
int numClients = GetClientsInRange(vPos, RangeType_Visibility, targets, MAXPLAYERS);
if( numClients == 0 )
{
#if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
StopProfiling(g_Prof);
float speed = GetProfilerTime(g_Prof);
if( speed < g_fBenchMin ) g_fBenchMin = speed;
if( speed > g_fBenchMax ) g_fBenchMax = speed;
g_fBenchAvg += speed;
g_iBenchTicks++;
#endif
#if DEBUG_BENCHMARK == 2
PrintToServer("ChooseVictim End 2 in %f (Min %f. Avg %f. Max %f)", speed, g_fBenchMin, g_fBenchAvg / g_iBenchTicks, g_fBenchMax);
#endif
delete aTargets;
return MRES_Ignored;
}
// =========================
// GET DISTANCE
// =========================
float vTarg[3];
float dist;
int team;
int index;
int victim;
for( int i = 0; i < numClients; i++ )
{
victim = targets[i];
if( victim && IsPlayerAlive(victim) )
{
// Option "voms" then allow choosing team 3
team = GetClientTeam(victim);
if( team == 2 || (team == 3 && g_iVomsOption[class] == 1) )
{
GetClientAbsOrigin(victim, vTarg);
dist = GetVectorDistance(vPos, vTarg);
index = aTargets.Push(dist);
aTargets.Set(index, victim, 1);
aTargets.Set(index, team, 2);
}
}
}
// Sort by nearest
SortADTArray(aTargets, Sort_Ascending, Sort_Float);
// =========================
// ALL INCAPPED CHECK
// OPTION: "incap" "3"
// =========================
// 3=Only attack incapacitated when everyones incapacitated.
bool allIncap;
if( g_iIncapOption[class] == 3 )
{
allIncap = true;
for( int i = 1; i <= MaxClients; i++ )
{
if( IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) )
{
if( g_bIncapped[i] == false )
{
allIncap = false;
break;
}
}
}
}
// =========================
// ORDER VALIDATION
// =========================
// Loop through all orders progressing to the next on fail, and each time loop through all survivors from nearest to test the order preference
bool allPinned = true;
int order;
int len = aTargets.Length;
int orders;
for( ; orders < MAX_ORDERS; orders++ )
{
// Found someone, exit loop
#if DEBUG_BENCHMARK == 3
PrintToServer("=== ORDER LOOP %d. newVictim %d (%N)", orders, newVictim, newVictim);
#endif
if( newVictim ) break;
// =========================
// OPTION: "order"
// =========================
switch( class )
{
case INDEX_TANK: order = g_iOrderTank[orders];
case INDEX_SMOKER: order = g_iOrderSmoker[orders];
case INDEX_BOOMER: order = g_iOrderBoomer[orders];
case INDEX_HUNTER: order = g_iOrderHunter[orders];
case INDEX_SPITTER: order = g_iOrderSpitter[orders];
case INDEX_JOCKEY: order = g_iOrderJockeys[orders];
case INDEX_CHARGER: order = g_iOrderCharger[orders];
}
// =========================
// LOOP SURVIVORS
// =========================
for( int i = 0; i < len; i++ )
{
victim = aTargets.Get(i, 1);
// All incapped, target nearest
if( allIncap )
{
#if DEBUG_BENCHMARK == 3
PrintToServer("Break allIncap");
#endif
newVictim = victim;
break;
}
team = aTargets.Get(i, 2);
// dist = aTargets.Get(i, 0);
// =========================
// OPTION: "incap"
// =========================
// 0=Ignore incapacitated players.
// 1=Allow attacking incapacitated players.
// 2=Only attack incapacitated players when they are vomited.
// 3=Only attack incapacitated when everyones incapacitated.
// 3 is already checked above.
if( team == 2 &&
g_bIncapped[victim] == true &&
g_bIncapped[victim] == false
)
{
switch( g_iIncapOption[class] )
{
case 0: continue;
case 2: if( g_bPinBoomer[victim] == false ) continue;
}
}
// =========================
// OPTION: "pinned"
// =========================
// Validate pinned and allowed
// 1=Smoker. 2=Hunter. 4=Jockey. 8=Charger.
if( team == 2 )
{
if( g_iPinnedOption[class] & 1 && g_bPinSmoker[victim] ) continue;
if( g_iPinnedOption[class] & 2 && g_bPinHunter[victim] ) continue;
if( g_bLeft4Dead2 )
{
if( g_iPinnedOption[class] & 4 && g_bPinJockey[victim] ) continue;
if( g_iPinnedOption[class] & 8 && g_bPinCharger[victim] ) continue;
}
allPinned = false;
}
// =========================
// OPTION: "order"
// =========================
newVictim = OrderTest(attacker, victim, team, order);
#if DEBUG_BENCHMARK == 3
PrintToServer("Order %d newVictim %d (%N)", order, newVictim, newVictim);
#endif
if( newVictim ) break;
}
}
// All pinned and not allowed to target, target self to avoid attacking pinned.
if( allPinned && g_iPinnedOption[class] == 0 )
{
newVictim = attacker;
}
// =========================
// NEW TARGET
// =========================
if( newVictim != g_iLastVictim[attacker] )
{
g_iLastOrders[attacker] = orders;
g_iLastVictim[attacker] = newVictim;
g_fLastSwitch[attacker] = GetGameTime() + g_fWaitOption[class];
}
// =========================
// OVERRIDE VICTIM
// =========================
if( newVictim )
{
DHookSetReturn(hReturn, newVictim);
#if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
StopProfiling(g_Prof);
float speed = GetProfilerTime(g_Prof);
if( speed < g_fBenchMin ) g_fBenchMin = speed;
if( speed > g_fBenchMax ) g_fBenchMax = speed;
g_fBenchAvg += speed;
g_iBenchTicks++;
#endif
#if DEBUG_BENCHMARK == 2
PrintToServer("ChooseVictim End 3 in %f (Min %f. Avg %f. Max %f)", speed, g_fBenchMin, g_fBenchAvg / g_iBenchTicks, g_fBenchMax);
#endif
delete aTargets;
return MRES_Supercede;
}
#if DEBUG_BENCHMARK == 1 || DEBUG_BENCHMARK == 2
StopProfiling(g_Prof);
float speed = GetProfilerTime(g_Prof);
if( speed < g_fBenchMin ) g_fBenchMin = speed;
if( speed > g_fBenchMax ) g_fBenchMax = speed;
g_fBenchAvg += speed;
g_iBenchTicks++;
#endif
#if DEBUG_BENCHMARK == 2
PrintToServer("ChooseVictim End 4 in %f (Min %f. Avg %f. Max %f)", speed, g_fBenchMin, g_fBenchAvg / g_iBenchTicks, g_fBenchMax);
#endif
delete aTargets;
return MRES_Ignored;
}
Also it looks like you edited the code somewhat line 699 has nothing but a comment.
|