Junior Member
Join Date: Jan 2017
Location: Korea
|
04-11-2020
, 03:06
Re: [TF2] How Fix Infinite loop occurs during array deletion
|
#5
|
Quote:
Originally Posted by Bacardi
Could you show your "updated" code ?
Try follow dump file for open handles etc. etc.
sm_dump_handles handles1.txt
And if server have run a while, check again.
sm_dump_handles handles2.txt
Compare those two files.
|
This is the native function I used in addition to this plugin.
PHP Code:
bool CheckInPlayer(int client)
{
if (client > 0 && client <= MaxClients)
{
if (IsClientInGame(client) == true)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
public int Native_CheckWeapon(Handle _Plugin, int _NumParams) // This Func is BU_IsCorrectWeapon(int _Attacker, int _WeaponIDX, bool _ChkClass, TFClassType _ClassType)
{
int atker = GetNativeCell(1);
int idx = GetNativeCell(2);
bool checkClass = GetNativeCell(3);
TFClassType classType = GetNativeCell(4);
if (CheckInPlayer(atker))
{
int weaponID = GetEntPropEnt(atker, Prop_Send, "m_hActiveWeapon");
int weaponName = GetEntProp(weaponID, Prop_Send, "m_iItemDefinitionIndex");
if (checkClass)
{
if (TF2_GetPlayerClass(atker) == classType)
{
if (weaponName == idx)
{
return true;
}
}
}
else
{
if (weaponName == idx)
{
return true;
}
}
}
return false;
}
public int Native_CheckUser(Handle _Plugin, int _NumParams) // This Func is BU_IsValidUser(int _Entity, bool _IsAlive = false);
{
int entity = GetNativeCell(1);
bool isAlive = GetNativeCell(2);
if (entity <= 0 || entity > MaxClients)
{
return false;
}
if (isAlive)
{
return IsClientInGame(entity) && IsPlayerAlive(entity);
}
return IsClientInGame(entity);
}
and Updated Codes.
PHP Code:
#pragma semicolon 1
#define DEBUG
#pragma dynamic 131072
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#include <clientprefs>
#include <morecolors>
#include <tf2items>
#include <tf2attributes>
#include <tf2>
#include <tf2_stocks>
#include <freak_fortress_2>
#include <BossUtil>
#pragma newdecls required
#define SMOKE "sprites/steam1.vmt"
#define LIGHTNING "sprites/lgtning.vmt"
#define SOUND_ZAP "misc/halloween/spell_lightning_ball_impact.wav"
#define BLACK { 0, 0, 0, 255 }
#define GREEN { 0, 255, 0, 255 }
#define YELLOW { 255, 255, 0, 255 }
#define ORANGE { 255, 165, 0, 255 }
#define RED { 255, 0, 0, 255 }
#define NAVY { 0, 0, 128, 255 }
#define BLUE { 0, 0, 255, 255 }
#define PURPLE { 255, 0, 255, 255 }
#define TEAL { 0, 128, 128, 255 }
#define PINK { 255, 192, 203, 255 }
#define AQUAMARINE { 127, 255, 212, 255 }
#define PEACHPUFF { 255, 218, 185, 255}
#define WHITE { 255, 255, 255, 255}
ConVar g_Activated, g_Distance, g_Targets, g_Damage, g_Unify, g_Crits, g_ColorIdx;
bool g_Enabled[MAXPLAYERS + 1];
int g_Color[4];
int g_LightSprite; // Sprite
public void OnPluginStart()
{
g_Activated = CreateConVar("sm_cl_activate", "1", "Activate Chain Lightning");
g_Distance = CreateConVar("sm_cl_distance", "300", "Chain's Distance");
g_Targets = CreateConVar("sm_cl_targets", "3", "Set Targets");
g_Damage = CreateConVar("sm_cl_damage", "1.0", "Set Damage Multifly");
g_Unify = CreateConVar("sm_cl_unify", "1", "Set Equal Damage");
g_Crits = CreateConVar("sm_cl_crits", "0", "Is Only Activate the Crits");
g_ColorIdx = CreateConVar("sm_cl_colors", "1", "Set Chain's Colors");
AutoExecConfig(true, "Custom_Lightning");
}
public void OnMapStart()
{
g_Color = AQUAMARINE;
g_LightSprite = PrecacheModel(LIGHTNING);
PrecacheSound(SOUND_ZAP, true);
}
public void OnClientPutInServer(int client)
{
g_Enabled[client] = g_Activated.BoolValue;
if (g_Enabled[client])
{
SDKHook(client, SDKHook_OnTakeDamageAlive, Event_OnTakeDamageAlive);
}
}
/*
public void OnClientDisconnect(int client)
{
if (g_Enabled[client])
{
SDKUnhook(client, SDKHook_OnTakeDamageAlive, Event_OnTakeDamageAlive);
}
}*/
stock void GetLightningColor()
{
switch (g_ColorIdx.IntValue)
{
case 1:g_Color = BLACK;
case 2:g_Color = GREEN;
case 3:g_Color = YELLOW;
case 4:g_Color = ORANGE;
case 5:g_Color = RED;
case 6:g_Color = NAVY;
case 7:g_Color = BLUE;
case 8:g_Color = PURPLE;
case 9:g_Color = TEAL;
case 10:g_Color = PINK;
case 11:g_Color = AQUAMARINE;
case 12:g_Color = PEACHPUFF;
case 13:g_Color = WHITE;
}
}
public Action Event_OnTakeDamageAlive(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3])
{
if (BU_IsValidUser(attacker, true))
{
if (!(damagetype & DMG_CRIT) && g_Crits.BoolValue)
{
return Plugin_Continue;
}
if (g_Unify.BoolValue)
{
damage = damage * g_Damage.FloatValue;
return Plugin_Changed;
}
if (IsActiveFunction(attacker, victim))
{
if (IsActiveWeapon(attacker))
{
ArrayList targets = new ArrayList();
float tPos[3]; // Target Position
for (int target = 1; target <= MaxClients; target++) // Push Valid Targets Loop.
{
// Client is in game or empty slot
if (!IsClientInGame(target))continue;
if (IsValidTarget(target, victim, attacker, TFTeam_Red))
{
GetClientAbsOrigin(target, tPos);
tPos[2] = damagePosition[2];
float dist = GetVectorDistance(damagePosition, tPos);
if (RoundToFloor(dist) <= g_Distance.IntValue)
{
targets.Push(target);
}
}
}
// no min. bound on ConVar, you could set as -1 ?
int total_targets = !g_Targets ? GetRandomInt(1, 5) : g_Targets.IntValue;
//int array_length = targets.Length; // Doesn't hurt if we use Length
// check is Array empty, then don't do extra work
// What if Cvar sm_cl_targets have set -1 ? Re-check variable total_targets
if (targets.Length <= 0 || total_targets <= 0)
{
// Remember delete ArrayList;
delete targets;
return Plugin_Continue;
}
if (total_targets > targets.Length)
{
total_targets = targets.Length;
}
if (total_targets)
{
//Stops the sound so it doesn't overlap over each other and cause a loud pitch sound
EmitAmbientSound(SOUND_ZAP, damagePosition, victim, _, SND_STOPLOOPING, _, _, _);
EmitAmbientSound(SOUND_ZAP, damagePosition, victim, SNDLEVEL_GUNFIRE, SND_NOFLAGS, 1.0, SNDPITCH_HIGH, 0.0);
}
for (int x = 0; x < total_targets; x++) // FIXME : WatchDogError in this section.
{
// ERROR ? Array empty
if (targets.Length <= 0)continue;
int i = GetRandomInt(0, targets.Length - 1);
int target = targets.Get(i);
GetClientAbsOrigin(target, tPos);
tPos[2] = damagePosition[2];
GetLightningColor();
TE_SetupBeamPoints(damagePosition, tPos, g_LightSprite, 0, 0, 0, 0.2, 10.0, 1.0, 10, 10.0, g_Color, 1);
TE_SendToAll();
SDKHooks_TakeDamage(target, 0, attacker, g_Unify.BoolValue ? damage * g_Damage.FloatValue : damage * g_Damage.FloatValue, DMG_DISSOLVE);
targets.Erase(i);
//array_length--; // we use targets.Length
//total_targets--; we use for loop
}
delete targets;
return Plugin_Continue;
}
}
}
return Plugin_Continue;
}
stock bool IsActiveFunction(int _Attacker, int _Victim)
{
if (g_Activated.IntValue || g_Enabled[_Attacker])
{
if (BU_IsValidUser(_Victim, true))
{
if (_Attacker != _Victim)
{
return true;
}
}
}
return false;
}
stock bool IsValidTarget(int _Target, int _Victim, int _Attacker, TFTeam _Team)
{
if (BU_IsValidUser(_Target, true))
{
if (TF2_GetClientTeam(_Target) == _Team && _Target != _Attacker)
{
return true;
}
}
return false;
}
stock bool IsActiveWeapon(int _Attacker)
{
if (TF2_GetClientTeam(_Attacker) == TFTeam_Blue)
{
if (IsValidEntity(GetEntPropEnt(_Attacker, Prop_Send, "m_hActiveWeapon")))
{
if (BU_IsCorrectWeapon(_Attacker, 30667, true, TFClass_Sniper))
{
return true;
}
}
}
return false;
}
This time, the error occurred when a summoner using the plug-in was damage in the first round.
I will ask the server owner to get the dump file as soon as possible.
TODO : Summoner Plug-in in use
We're using "clone attack" from "Freak Fortress 2" and there's a problem with the two types of Summoners not available, so the server is using a plug-in that replicates them.
|
|