In topic first post, it looks like classic mistake with timers.
You create
repeated timer and
stored on handle, problem is that you use also timer flag
TIMER_FLAG_NO_MAPCHANGE.
Timer will stop and disappear on map load, but it will not clear the handle,
you have old address of that non exist timer.
For quick fix, you should remove all timer code from OnPluginStart().
Then remove all checks on OnMapStart(), just create timer straight on that handle.
Anyway, here random plugin example.
I used @101 idea also, using sdkhooks OnEntityCreated.
PHP Code:
#include <sdktools>
#include <sdkhooks>
enum struct WpInfo
{
int entref;
int timestamp;
}
Handle hTimer;
ArrayList listent;
bool IsRoundFreezeEnd = true;
// Weapon m_iState
#define WEAPON_IS_ONTARGET 0x40 // weapon currently auto-aimed (hl2 legacy code ?)
#define WEAPON_NOT_CARRIED 0 // Weapon is on the ground
#define WEAPON_IS_CARRIED_BY_PLAYER 1 // This client is carrying this weapon.
#define WEAPON_IS_ACTIVE 2 // This client is carrying this weapon and it's the currently held weapon
const int threshold = 18;
public void OnPluginStart()
{
HookEventEx("round_freeze_end", round_freeze_end);
listent = new ArrayList(sizeof(WpInfo));
}
public void OnMapStart()
{
IsRoundFreezeEnd = true;
listent.Clear();
delete hTimer;
}
public void round_freeze_end(Event event, const char[] name, bool dontBroadcast)
{
listent.Clear();
CreateTimer(1.0, delay, _, TIMER_FLAG_NO_MAPCHANGE); // lets make sure, map own weapon entities are spawned
}
public Action delay(Handle timer)
{
IsRoundFreezeEnd = false;
hTimer = CreateTimer(2.0, TimerCheck, _, TIMER_REPEAT);
return Plugin_Continue;
}
public void OnEntityCreated(int entity, const char[] classname)
{
if(IsRoundFreezeEnd)
return;
if(StrContains(classname, "weapon_", false) == 0)
{
SDKHook(entity, SDKHook_SpawnPost, SpawnPost);
}
}
public void SpawnPost(int entity)
{
if(!HasEntProp(entity, Prop_Send, "m_iState"))
return;
WpInfo info;
info.entref = EntIndexToEntRef(entity);
info.timestamp = GetTime();
listent.PushArray(info, sizeof(WpInfo));
}
public Action TimerCheck(Handle timer)
{
if(hTimer == null || hTimer != timer)
return Plugin_Stop;
int listentsize = listent.Length;
// Treshold when start remove weapons
if(listentsize <= threshold)
return Plugin_Continue;
WpInfo info;
int time = GetTime();
int ent;
for(int x = 0; listentsize > threshold && x < listentsize; x++)
{
listent.GetArray(x, info, sizeof(WpInfo));
ent = EntRefToEntIndex(info.entref);
if(ent == -1)
{
listent.Erase(x);
x--, listentsize--;
continue;
}
if(GetEntProp(ent, Prop_Send, "m_iState") == WEAPON_NOT_CARRIED)
{
if( (time - info.timestamp) <= 60 ) // new weapon stay on ground about 60 seconds when not pickup
continue;
AcceptEntityInput(ent, "Kill");
listent.Erase(x);
x--, listentsize--;
}
else
{
// refresh timestamp
info.timestamp = time;
listent.SetArray(x, info, sizeof(WpInfo));
}
}
/*
char classname[64];
int ent = -1;
while((ent = FindEntityByClassname(ent, "weapon_*")) != -1)
{
if(!HasEntProp(ent, Prop_Send, "m_iState")
|| GetEntProp(ent, Prop_Send, "m_iState") != WEAPON_NOT_CARRIED)
continue;
// Do code here
GetEntityClassname(ent, classname, sizeof(classname));
PrintToServer("%i ent %s", ent, classname);
}
*/
return Plugin_Continue;
}
Plugin save weapon entities, what are created after round_freeze_end event, into arraylist.
These weapons in arraylist get removed only, when those exceed over 18 limit.
These new weapons have 60 seconds timelimit when on ground and not picked.
When new weapon is picked up again from ground, time get reset.
- For extra, there is code snippet how you can loop all weapons on map what are not carried.
__________________