Thread: [Solved] When are handles closed?
View Single Post
NIGathan
Senior Member
Join Date: Aug 2011
Location: /dev/null
Old 02-11-2019 , 22:33   Re: When are handles closed?
Reply With Quote #7

Quote:
Originally Posted by Powerlord View Post
Are these ArrayLists and StringMaps created by your plugin or a different plugin?
Yes, my plugin is creating them.
Quote:
Originally Posted by asherkin View Post
Impossible to tell without seeing your code, but you may be hitting https://github.com/alliedmodders/sourcepawn/issues/310 if you're using enum struct methods.

HandleError_Index is generally "that is not, and could not have been, a handle", which is what makes me suspect that issue.
No, I was the one who discovered that bug, I've been very careful to avoid it at all costs. The only enum struct methods I'm using are voids.

My plugin started as this and I expanded it so that another methodmap of an ArrayList is filled with the MapReward methodmaps.

Here are the snippets of my code in question:

enum struct used as a container to convert the StringMap data to->from:
PHP Code:
enum struct MapRewardEntity
{
    
int id;
    
int Edict;
    
char Name[MAXNAME];
    
char Entity[MAXENTITY];
    
char Model[MAXMODEL];
    
char Override[MAXSCRIPT];
    
char Dispatch[MAXSCRIPT];
    
char Property[MAXSCRIPT];
    
float SpawnOrigin[3];
    
float SpawnAngles[3];
    
float Angles[3];
    
float SpinAngles[3];
    
float SpinInterval;
    
Handle SpinTimer;
    
char Command[MAXCMD];
    
char HurtCommand[MAXCMD];
    
int Attribute;
    
float Health;
    
float Damage;
    
bool Evaluated;
    
float Respawn;
    
int Overlay;
    
void Evaluate()
    {
        if (!
this.Evaluated)
        {
            
bool beenSet[4];
            if (
strlen(this.Property) > 0)
            {
                
ScriptAliases.Get(this.Property,this.Property); // make sure these aren't resetting the variable if they aren't being set, otherwise an if Get to temp -> strcopy will be needed.
                
beenSet[3] = true;
            }
            if (
strlen(this.Dispatch) > 0)
            {
                
ScriptAliases.Get(this.Dispatch,this.Dispatch);
                
beenSet[2] = true;
            }
            if (
strlen(this.Override) > 0)
            {
                
ScriptAliases.Get(this.Override,this.Override);
                
beenSet[1] = true;
            }
            if (
strlen(this.Model) > 0)
            {
                
ModelAliases.Get(this.Model,this.Model);
                
beenSet[0] = true;
            }
            if (
strlen(this.Entity) > 0)
            {
                
MapRewardEntityAlias alias;
                
EntityAliases.Get(this.Entity,alias);
                
strcopy(this.Entity,MAXENTITY,alias.Entity);
                if ((!
beenSet[0]) && (strlen(alias.Model) > 0))
                    
strcopy(this.Model,MAXMODEL,alias.Model);
                if ((!
beenSet[1]) && (strlen(alias.Override) > 0))
                    
strcopy(this.Override,MAXSCRIPT,alias.Override);
                if ((!
beenSet[2]) && (strlen(alias.Dispatch) > 0))
                    
strcopy(this.Dispatch,MAXSCRIPT,alias.Dispatch);
                if ((!
beenSet[3]) && (strlen(alias.Property) > 0))
                    
strcopy(this.Property,MAXSCRIPT,alias.Property);
            }
        }
        if ((
strlen(this.Entity) < 1) || (strcmp(this.Entity,"null") == 0))
            
strcopy(this.Entity,MAXENTITY,"prop_physics_override");
        if (
strcmp(this.Model,"null") == 0)
            
strcopy(this.Model,MAXMODEL,"");
        if (
strcmp(this.Override,"null") == 0)
            
strcopy(this.Override,MAXSCRIPT,"");
        if (
strcmp(this.Dispatch,"null") == 0)
            
strcopy(this.Dispatch,MAXSCRIPT,"");
        if (
strcmp(this.Property,"null") == 0)
            
strcopy(this.Property,MAXSCRIPT,"");
    }
}; 
Here is the expanded MapReward methodmap, this.handle is what is being stored into the ArrayList:
PHP Code:
int rewardCount;

methodmap MapReward __nullable__
{
    public 
MapReward()
    {
        
StringMap handle = new StringMap();
        
handle.SetValue("id",rewardCount++);
        
handle.SetValue("edict",-1);
        
handle.SetString("name","");
        
handle.SetString("entity","");
        
handle.SetString("model","");
        
handle.SetString("override","");
        
handle.SetString("dispatch","");
        
handle.SetString("prop","");
        
float vec[3];
        
handle.SetArray("defOrigin",vec,3);
        
handle.SetArray("defAngles",vec,3);
        
handle.SetArray("angles",vec,3);
        
handle.SetArray("spinAngles",vec,3);
        
handle.SetValue("spinInt",0.0);
        
handle.SetValue("spinTimer",INVALID_HANDLE);
        
handle.SetString("command","");
        
handle.SetString("hurtCommand","");
        
handle.SetValue("attribute",0);
        
handle.SetValue("health",0.0);
        
handle.SetValue("damage",0.0);
        
handle.SetValue("eval",1);
        
handle.SetValue("respawn",-1.0);
        
handle.SetValue("overlay",FULLSPECTRUM);
        
handle.SetValue("attacker",-1);
        
handle.SetValue("inflictor",-1);
        
handle.SetValue("tickDamage",0.0);
        return 
view_as<MapReward>(handle);
    }
    
/*public MapReward(MapRewardEntity reward)
    {
        StringMap handle = new StringMap();
        handle.SetValue("edict",reward.Edict);
        handle.SetString("name",reward.Name);
        handle.SetString("entity",reward.Entity);
        handle.SetString("model",reward.Model);
        handle.SetArray("origin",reward.SpawnOrigin,3);
        handle.SetArray("angles",reward.SpawnAngles,3);
        return view_as<MapReward>(handle);
    }*/// Shame you can't overload :(
    /*public ~MapReward()
    {
        //CloseHandle(this.handle.get());
        delete this;
    }*/// Does the default destructor do this automatically? Shame they removed destructors...
    
property StringMap handle
    
{
        public 
get()
        {
            return 
view_as<StringMap>(this);
        }
    }
    
property bool Evaluated
    
{
        public 
get()
        {
            
int eval;
            
this.handle.GetValue("eval",eval);
            if (eval)
                return 
true;
            return 
false;
        }
        public 
set(bool eval)
        {
            if (eval)
            {
                
int val;
                
this.handle.GetValue("eval",val);
                if (!
val)
                {
                    
MapRewardEntity reward;
                    
this.handle.GetString("entity",reward.Entity,MAXENTITY);
                    
this.handle.GetString("model",reward.Model,MAXMODEL);
                    
this.handle.GetString("override",reward.Override,MAXSCRIPT);
                    
this.handle.GetString("dispatch",reward.Dispatch,MAXSCRIPT);
                    
this.handle.GetString("prop",reward.Property,MAXSCRIPT);
                    
reward.Evaluated false;
                    
reward.Evaluate();
                    
this.handle.SetString("entity",reward.Entity,true);
                    
this.handle.SetString("model",reward.Model,true);
                    
this.handle.SetString("override",reward.Override,true);
                    
this.handle.SetString("dispatch",reward.Dispatch,true);
                    
this.handle.SetString("prop",reward.Property,true);
                }    
                
this.handle.SetValue("eval",1,true);
            }
            else
                
this.handle.SetValue("eval",0,true);
        }
    }
    
property int ID
    
{
        public 
get()
        {
            
int id;
            
this.handle.GetValue("id",id);
            return 
id;
        }
    }
    
property int Edict
    
{
        public 
get()
        {
            
int edict;
            
this.handle.GetValue("edict",edict);
            return 
edict;
        }
        public 
set(int edict)
        {
            
this.handle.SetValue("edict",edict,true);
        }
    }
    public 
void GetData(MapRewardEntity reward)
    {
        
this.handle.GetValue("id",reward.id);
        
this.handle.GetValue("edict",reward.Edict);
        
this.handle.GetString("name",reward.Name,MAXNAME);
        
this.handle.GetString("entity",reward.Entity,MAXENTITY);
        
this.handle.GetString("model",reward.Model,MAXMODEL);
        
this.handle.GetString("override",reward.Override,MAXSCRIPT);
        
this.handle.GetString("dispatch",reward.Dispatch,MAXSCRIPT);
        
this.handle.GetString("prop",reward.Property,MAXSCRIPT);
        
float vec[3];
        
int sizevec sizeof(vec);
        
this.handle.GetArray("defOrigin",reward.SpawnOrigin,sizevec);
        
this.handle.GetArray("defAngles",reward.SpawnAngles,sizevec);
        
this.handle.GetArray("angles",reward.Angles,sizevec);
        
this.handle.GetArray("spinAngles",reward.SpinAngles,sizevec);
        
this.handle.GetValue("spinInt",reward.SpinInterval);
        
this.handle.GetValue("spinTimer",reward.SpinTimer);
        
this.handle.GetString("command",reward.Command,MAXCMD);
        
this.handle.GetString("hurtCommand",reward.HurtCommand,MAXCMD);
        
this.handle.GetValue("attribute",reward.Attribute);
        
this.handle.GetValue("health",reward.Health);
        
this.handle.GetValue("damage",reward.Damage);
        
this.handle.GetValue("eval",sizevec);
        
reward.Evaluated = (sizevec != 0);
        
this.handle.GetValue("respawn",reward.Respawn);
        
this.handle.GetValue("overlay",reward.Overlay);
    }
    public 
void SetData(const MapRewardEntity reward)
    {
        
int oldID = -1;
        
this.handle.GetValue("id",oldID);
        if ((
oldID 0) || (oldID >= rewardCount))
            
this.handle.SetValue("id",reward.id,true);
        
this.handle.SetValue("edict",reward.Edict,true);
        
this.handle.SetString("name",reward.Name,true);
        
this.handle.SetString("entity",reward.Entity,true);
        
this.handle.SetString("model",reward.Model,true);
        
this.handle.SetString("override",reward.Override,true);
        
this.handle.SetString("dispatch",reward.Dispatch,true);
        
this.handle.SetString("prop",reward.Property,true);
        
this.handle.SetArray("defOrigin",reward.SpawnOrigin,3,true);
        
this.handle.SetArray("defAngles",reward.SpawnAngles,3,true);
        
this.handle.SetArray("angles",reward.Angles,3,true);
        
this.handle.SetArray("spinAngles",reward.SpinAngles,3,true);
        
this.handle.SetValue("spinInt",reward.SpinInterval,true);
        
this.handle.SetValue("spinTimer",reward.SpinTimer,true);
        
this.handle.SetString("command",reward.Command,true);
        
this.handle.SetString("hurtCommand",reward.HurtCommand,true);
        
this.handle.SetValue("attribute",reward.Attribute,true);
        
this.handle.SetValue("health",reward.Health,true);
        
this.handle.SetValue("damage",reward.Damage,true);
        if (
reward.Evaluated)
            
this.handle.SetValue("eval",1,true);
        else
            
this.handle.SetValue("eval",0,true);
        
this.handle.SetValue("respawn",reward.Respawn,true);
        
this.handle.SetValue("overlay",reward.Overlay,true);
    }
    public 
bool IsValid()
    {
        
int edict this.Edict;
        if ((
edict > -1) && (IsValidEntity(edict)))
        {
            
char iName[MAXNAME];
            
char name[MAXNAME];
            
this.GetName(name);
            
GetEntPropString(edict,Prop_Data,"m_iName",iName,MAXNAME);
            if (
strcmp(iName,name) == 0)
                return 
true;
        }
        
this.Edict = -1;
        return 
false;
    }
    public 
void Kill()
    {
        if (
this.IsValid())
            
AcceptEntityInput(this.Edict,"Kill",0,0,0);
        
this.Edict = -1;
    }
    public 
bool Summon()
    {
        
this.Damage 0.0;
        
MapRewardEntity reward;
        
this.GetData(reward);
        if (
reward.Attribute HOOK_DEACTIVE)
        {
            if (
IsValidEntity(reward.Edict))
            {
                if (
this.IsValid())
                {
                    
this.Attribute &= ~HOOK_DEACTIVE;
                    if (
reward.Attribute HOOK_TOUCH)
                        
SDKHook(reward.Edict,SDKHook_StartTouch,MapRewardPickUp);
                    if (
reward.Attribute HOOK_HURT)
                        
SDKHook(reward.Edict,SDKHook_OnTakeDamage,MapRewardTakeDamage);
                    return 
true;
                }
            }
            else if (!(
reward.Attribute HOOK_STATIC))
            {
                if (
reward.Respawn 0.0)
                    
CreateTimer(cVars.respawnTime,TimerRespawnReward,view_as<MapReward>(this));
                else if (
reward.Respawn 0.0)
                    
CreateTimer(reward.Respawn,TimerRespawnReward,view_as<MapReward>(this));
                return 
true;
            }
        }
        
this.Kill();
        
reward.Edict CreateEntityByName(reward.Entity);
        if (
IsValidEntity(reward.Edict))
        {
            
SetEntPropString(reward.Edict,Prop_Data,"m_iName",reward.Name);
            
reward.Evaluate();
            if (
strlen(reward.Model) > 0)
                
//SetEntityModel(reward.Edict,reward.Model);
                
DispatchKeyValue(reward.Edict,"model",reward.Model);
            
DispatchSpawn(reward.Edict);
            if (
strlen(reward.Override) > 0)
                
DispatchKeyValue(reward.Edict,"overridescript",reward.Override);
            if (
strlen(reward.Dispatch) > 0)
            {
                
char strCurrent[MAXSCRIPT];
                
char strKeys[2][MAXSCRIPT];
                
char strType[16];
                
StrCat(reward.Dispatch,MAXSCRIPT,"&");
                while (
SplitString(reward.Dispatch,"&",strCurrent,MAXSCRIPT) > -1)
                {
                    if (
StrContains(strCurrent,",") < 0)
                        
AcceptEntityInput(reward.Edict,strCurrent,-1,-1,0);
                    else
                    {
                        
ExplodeString(strCurrent,",",strKeys,2,MAXSCRIPT,true);
                        
SplitString(strKeys[1],"=",strType,16);
                        
StrCat(strType,16,"=");
                        
ReplaceStringEx(strKeys[1],MAXSCRIPT,strType,"",-1,0);
                        if (
strcmp(strType,"float=") == 0)
                            
DispatchKeyValueFloat(reward.Edict,strKeys[0],StringToFloat(strKeys[1]));
                        else if (
strcmp(strType,"vec=") == 0)
                        {
                            
float vec[3];
                            
char strVec[3][16];
                            
ExplodeString(strKeys[1],",",strVec,3,16,true);
                            for (
int i 0;3;i++)
                                
vec[i] = StringToFloat(strVec[i]);
                            
DispatchKeyValueVector(reward.Edict,strKeys[0],vec);
                        }
                        else
                            
DispatchKeyValue(reward.Edict,strKeys[0],strKeys[1]);
                    }
                    
ReplaceStringEx(reward.Dispatch,MAXSCRIPT,strCurrent,"",-1,0);
                    if (
reward.Dispatch[0] == '&')
                        
StrErase(reward.Dispatch,0,1);
                }
            }
            if (
strlen(reward.Property) > 0)
            {
                
char strCurrent[MAXSCRIPT];
                
char strKeys[2][MAXSCRIPT];
                
char strType[16];
                
PropType propType;
                
StrCat(reward.Property,MAXSCRIPT,"&");
                while (
SplitString(reward.Property,"&",strCurrent,MAXSCRIPT) > -1)
                {
                    if (
StrContains(strCurrent,",") < 0)
                        
AcceptEntityInput(reward.Edict,strCurrent,-1,-1,0);
                    else
                    {
                        
propType Prop_Data;
                        if ((
strlen(strCurrent) > 2) && (strCurrent[1] == ':'))
                        {
                            if (
strCurrent[0] == '1')
                                
propType Prop_Send;
                            
StrErase(strCurrent,0,2);
                        }
                        
ExplodeString(strCurrent,",",strKeys,2,MAXSCRIPT,true);
                        
SplitString(strKeys[1],"=",strType,16);
                        
StrCat(strType,16,"=");
                        
ReplaceStringEx(strKeys[1],MAXSCRIPT,strType,"",-1,0);
                        if (
strcmp(strType,"float=") == 0)
                            
SetEntPropFloat(reward.Edict,propType,strKeys[0],StringToFloat(strKeys[1]));
                        else if (
strcmp(strType,"int=") == 0)
                            
SetEntProp(reward.Edict,propType,strKeys[0],StringToInt(strKeys[1]));
                        else if (
strcmp(strType,"bool=") == 0)
                            
SetEntProp(reward.Edict,propType,strKeys[0],StringToInt(strKeys[1]),1);
                        else if (
strcmp(strType,"vec=") == 0)
                        {
                            
float vec[3];
                            
char strVec[3][16];
                            
ExplodeString(strKeys[1],",",strVec,3,16,true);
                            for (
int i 0;3;i++)
                                
vec[i] = StringToFloat(strVec[i]);
                            
SetEntPropVector(reward.Edict,propType,strKeys[0],vec);
                        }
                        else if (
strcmp(strType,"ent=") == 0)
                            
SetEntPropEnt(reward.Edict,propType,strKeys[0],StringToInt(strKeys[1]));
                        else
                            
SetEntPropString(reward.Edict,propType,strKeys[0],strKeys[1]);
                    }
                    
ReplaceStringEx(reward.Property,MAXSCRIPT,strCurrent,"",-1,0);
                    if (
reward.Property[0] == '&')
                        
StrErase(reward.Property,0,1);
                }
            }
            if (
reward.Overlay != FULLSPECTRUM)
            {
                
int colors[4];
                
colors[0] = (reward.Overlay 0x000000FF);
                
colors[1] = (reward.Overlay 0x0000FF00) >> 8;
                
colors[2] = (reward.Overlay 0x00FF0000) >> 16;
                
colors[3] = (reward.Overlay 0xFF000000) >> 24;
                for (
int i 0;4;i++)
                    if (
colors[i] < 0)
                        
colors[i] = (colors[i] % 256) + 256;
                
SetEntityRenderMode(reward.Edict,RENDER_GLOW);
                
SetEntityRenderColor(reward.Edict,colors[0],colors[1],colors[2],colors[3]);
            }
            
float org[3];
            
float ang[3];
            for (
int i 0;3;i++)
            {
                
org[i] = reward.SpawnOrigin[i];
                
ang[i] = reward.SpawnAngles[i];
            }
            
TeleportEntity(reward.Edict,org,ang,NULL_VECTOR);
            
this.Edict reward.Edict;
            if (
reward.SpinInterval 0.0)
            {
                
this.SetSpinAngles(ang);
                
this.SetSpinTimer(CreateTimer(reward.SpinInterval,TimerSpin,view_as<MapReward>(this),TIMER_REPEAT));
            }
            if (
reward.Attribute HOOK_DEACTIVE)
            {
                if (
reward.Respawn 0.0)
                    
CreateTimer(cVars.respawnTime,TimerRespawnReward,view_as<MapReward>(this));
                else if (
reward.Respawn 0.0)
                    
CreateTimer(reward.Respawn,TimerRespawnReward,view_as<MapReward>(this));
            }
            else
            {
                if (
reward.Attribute HOOK_TOUCH)
                    
SDKHook(reward.Edict,SDKHook_StartTouch,MapRewardPickUp);
                if (
reward.Attribute HOOK_HURT)
                    
SDKHook(reward.Edict,SDKHook_OnTakeDamage,MapRewardTakeDamage);
            }
            return 
true;
        }
        return 
false;
    }
}; 
I left some bits out to try to shorten this.
Here is the methodmap that is filled with MapReward handles:
PHP Code:
methodmap MapRewardList __nullable__
{
    public 
MapRewardList()
    {
        
ArrayList handle = new ArrayList(1,1);
        return 
view_as<MapRewardList>(handle);
    }
    
property ArrayList handle
    
{
        public 
get()
        {
            return 
view_as<ArrayList>(this);
        }
    }
    
property int Count
    
{
        public 
get()
        {
            return 
this.handle.Length;
        }
    }
    public 
MapReward Get(int index)
    {
        if (-
index this.handle.Length)
            return 
view_as<MapReward>(this.handle.Get(index));
        return 
view_as<MapReward>(INVALID_HANDLE);
    }
    public 
MapReward GetEdict(int edictint &index = -1)
    {
        if (
IsValidEntity(edict))
        {
            
MapReward reward;
            for (
int i 0this.handle.Length;j;i++)
            {
                
reward view_as<MapReward>(this.handle.Get(i));
                if (
edict == reward.Edict)
                {
                    
index i;
                    return 
reward;
                }
            }
        }
        return 
view_as<MapReward>(INVALID_HANDLE);
    }
    public 
MapReward GetID(int idint &index = -1)
    {
        
MapReward reward;
        for (
int i 0this.handle.Length;j;i++)
        {
            
reward view_as<MapReward>(this.handle.Get(i));
            if (
id == reward.ID)
            {
                
index i;
                return 
reward;
            }
        }
        return 
view_as<MapReward>(INVALID_HANDLE);
    }
    public 
MapReward GetName(const char[] nameint &index = -1)
    {
        
MapReward reward;
        
char rewardName[MAXNAME];
        for (
int i 0this.handle.Length;j;i++)
        {
            
reward view_as<MapReward>(this.handle.Get(i));
            
reward.GetName(rewardName);
            if (
strcmp(name,rewardName) == 0)
            {
                
index i;
                return 
reward;
            }
        }
        return 
view_as<MapReward>(INVALID_HANDLE);
    }
    public 
bool IsValid(int idint &index = -1)
    {
        for (
int i 0this.handle.Length;j;i++)
        {
            if (
id == view_as<MapReward>(this.handle.Get(i)).ID)
            {
                
index i;
                return 
true;
            }
        }
        return 
false;
    }
    public 
int Add(MapReward reward)
    {
        return 
this.handle.Push(reward);
    }
    public 
int AddEntity(MapRewardEntity reward)
    {
        
MapReward entry = new MapReward();
        
entry.SetData(reward);
        
int r;
        
this.handle.Push(entry);
        
entry view_as<MapReward>(INVALID_HANDLE);
        return 
r;
    }
    public 
bool Remove(int indexbool kill true)
    {
        
StringMap reward;
        if (-
index this.handle.Length)
        {
            
reward this.handle.Get(index);
            if (
kill)
                
view_as<MapReward>(reward).Kill();
            
CloseHandle(reward);
            
this.handle.Erase(index);
            if (
this.handle.Length 1)
                
rewardCount 0;
            return 
true;
        }
        return 
false;
    }
    public 
void RemoveAll(bool kill true)
    {
        
StringMap reward;
        for (
int i 0,this.handle.Length;j;i++)
        {
            
reward this.handle.Get(i);
            if (
kill)
                
view_as<MapReward>(reward).Kill();
            
CloseHandle(reward);
        }
        
this.handle.Clear();
        
rewardCount 0;
    }
    public 
void Kill()
    {
        for (
int i 0this.handle.Length;j;i++)
            
view_as<MapReward>(this.handle.Get(i)).Kill();
    }
    public 
void Summon()
    {
        for (
int i 0,this.handle.Length;j;i++)
            
view_as<MapReward>(this.handle.Get(i)).Summon();
    }
};
MapRewardList MapRewards;

public 
void OnPluginStart()
{
    
cVars.Setup();
    
MapRewards = new MapRewardList();
    
EntityAliases = new MapRewardEntityAliases();
    
ModelAliases = new MapRewardModelAliases();
    
ScriptAliases = new MapRewardScriptAliases();
    
    
RegConsoleCmd("sm_mrw_info"InfoSpawnPoint"Displays info about a specific reward spawn point.");
    
RegConsoleCmd("sm_mrw_add"AddSpawnPoint"Sets a spawn point on the map for a reward.");

And here is a place where those MapReward's get recalled. This is the callback for an SKDHook_StartTouch event (created by MapReward::Summon()). It errors at MapRewardList::GetEdict():
PHP Code:
public Action MapRewardPickUp(int edictint client)
{
    if ((
cVars.enable) && (client 0) && (client <= MaxClients) && (IsClientInGame(client)))
    {
        
MapReward reward MapRewards.GetEdict(edict);
        if (
reward.handle != INVALID_HANDLE)
        {
            
reward.Trigger(client);
            if (
reward.Attribute HOOK_STATIC)
            {
                
SDKUnhook(edict,SDKHook_StartTouch,MapRewardPickUp);
                
reward.Attribute |= HOOK_DEACTIVE;
            }
            if (!(
reward.Attribute HOOK_CONSTANT))
            {
                if (!(
reward.Attribute HOOK_STATIC))
                    
reward.Kill();
                if (
reward.Respawn 0.0)
                    
CreateTimer(cVars.respawnTimeTimerRespawnRewardreward);
                else if (
reward.Respawn 0.0)
                    
CreateTimer(reward.RespawnTimerRespawnRewardreward);
            }
        }
        
reward view_as<MapReward>(INVALID_HANDLE);
    }

PHP Code:
public Action AddSpawnPoint(int clientint args)
{
    if (!
handleClientAccess(client,cVars.createFlag))
        return 
Plugin_Handled;
    if (
args 1)
    {
        
CRespondToCommand(client"[SM] Usage: sm_mrw_add [OPTIONS ...] [command ...]");
        
CRespondToCommand(client"[SM]   Use sm_mrw_add -h to see the full help. Note: It's long, may want to run it from console.");
        return 
Plugin_Handled;
    }
    
MapReward reward = new MapReward();
    
// Skipping tons of input-defined settings on the reward
    
if (cVars.enable)
    {
        
reward.Summon();
        if (
release)
            
CRespondToCommand(client"[SM] Added reward and released entity #%d",reward.Edict);
        else
            
CRespondToCommand(client"[SM] Added reward spawn point #%d(%d)",reward.ID,reward.Edict);
    }
    else
        
CRespondToCommand(client"[SM] Added reward spawn point #%d(%d)",reward.ID,reward.Edict);
    if (
release)
        
CloseHandle(reward.handle);
    else
    {
        
MapRewards.Add(reward);
        if (
client != 0)
            
autoSave(SAVE_EDIT,true);
    }
    
reward view_as<MapReward>(INVALID_HANDLE); // an attempt to reset the handle in case it was calling the destructor, the addition of this line changed nothing.
    
return Plugin_Handled;

Edit: I have attached the full plugin incase I left out something important above, sorry it's hard to pinpoint the exact location or reason of my issue.
Attached Files
File Type: sp Get Plugin or Get Source (transitional_test.sp - 88 views - 138.5 KB)

Last edited by NIGathan; 02-11-2019 at 22:54.
NIGathan is offline