#include <sourcemod>\r
-#define Version "0.1"\r
+#define Version "0.2"\r
\r
-new Handle:despawn;\r
+new Handle:despawn_weapons;\r
+new Handle:despawn_ammo;\r
+\r
+/* Array to track players grabbed ammo. */\r
+new grabbed_ammo[MAXPLAYERS];\r
+#define NAME_BUFFER_LEN 32\r
+new namebuffer[NAME_BUFFER_LEN];\r
+/* XXX: Surely this should be enough for ammo spawners. */\r
+#define NUM_AMMO_ENTITIES 32\r
+new ammo_entities[NUM_AMMO_ENTITIES];\r
+new ammo_counts[NUM_AMMO_ENTITIES];\r
\r
public Plugin:myinfo = {\r
name = "Limited weapons",\r
}\r
\r
/* Set up cvars. */\r
- despawn = CreateConVar("limited_weapons_despawn", "1", "Remove weapon spawners immediately after use.");\r
+ despawn_weapons = CreateConVar("lw_despawn_weapons", "1", "Remove weapon spawners immediately after use.");\r
+ despawn_ammo = CreateConVar("lw_despawn_ammo", "4", "Remove ammo spawners after this many uses. Set to 0 to disable removal.");\r
\r
- AutoExecConfig(true, "limited_weapons");\r
+ AutoExecConfig(true, "lw");\r
\r
/* Hooks. */\r
HookEvent("spawner_give_item", spawner_give_item_callback);\r
+ HookEvent("player_use", player_use_callback);\r
+ HookEvent("ammo_pickup", ammo_pickup_callback);\r
}\r
\r
-/* Remove item spawner as soon as it has given an item. */\r
+/* A player picked up an item from a spawner. */\r
public spawner_give_item_callback(Handle:event, const String:name[], bool:dontBroadcast) {\r
- if (GetConVarInt(despawn)) {\r
- new spawner = GetEventInt(event, "spawner");\r
- if (IsValidEntity(spawner)) RemoveEdict(spawner);\r
+ /* Remove item spawner as soon as it has given an item. */\r
+ if (! GetConVarInt(despawn_weapons)) return;\r
+\r
+ new spawner = GetEventInt(event, "spawner");\r
+ if (! IsValidEntity(spawner)) return;\r
+\r
+ GetEdictClassname(spawner, namebuffer, NAME_BUFFER_LEN);\r
+\r
+ LogMessage("Removing %s (%d) after use.", namebuffer, spawner);\r
+ RemoveEdict(spawner);\r
+}\r
+\r
+/* A player interacted with something. */\r
+public player_use_callback(Handle:event, const String:name[], bool:dontBroadcast) {\r
+ /*\r
+ By the time this fires the value of grabbed_ammo[userid] will be 1 \r
+ if ammo was picked up.\r
+ */\r
+ new count = GetConVarInt(despawn_ammo);\r
+ if (! count) return;\r
+\r
+ new userid = GetEventInt(event, "userid");\r
+ new was_ammo = grabbed_ammo[userid];\r
+ /* Forget that this player interacted with anything. */\r
+ grabbed_ammo[userid] = 0;\r
+\r
+ new spawner = GetEventInt(event, "targetid");\r
+ if (! IsValidEntity(spawner)) return;\r
+\r
+ if (! was_ammo) return;\r
+\r
+ /* Check this is an ammo spawner. Surely it must be. */\r
+ GetEdictClassname(spawner, namebuffer, NAME_BUFFER_LEN);\r
+ if (strcmp(namebuffer, "weapon_ammo_spawn")) return;\r
+\r
+ /* How many times? */\r
+ new index = get_ammo_index(spawner);\r
+ if (index == -1) return;\r
+\r
+ new used = ammo_counts[index] + 1;\r
+ ammo_counts[index] = used;\r
+\r
+ if (used >= count) {\r
+ LogMessage("Removing %s (%d) after %d use(s).", namebuffer, used, spawner);\r
+ RemoveEdict(spawner);\r
}\r
}\r
- \r
+\r
+/* A player took ammo. This is called before player_use.*/\r
+public ammo_pickup_callback(Handle:event, const String:name[], bool:dontBroadcast) {\r
+ /* Remember how many times the ammo was used. */\r
+ new count = GetConVarInt(despawn_ammo);\r
+ if (! count) return;\r
+\r
+ new userid = GetEventInt(event, "userid");\r
+\r
+ grabbed_ammo[userid] = 1;\r
+}\r
+\r
+/* Cheap hash-alike. */\r
+public int:get_ammo_index(int:entity) {\r
+ new i;\r
+ new count;\r
+ for (i = 0; i < NUM_AMMO_ENTITIES; i++) {\r
+ if (ammo_entities[i] == entity) return i;\r
+ else if (ammo_entities[i]) count++;\r
+ }\r
+\r
+ /* Is the array full? */\r
+ if (count >= NUM_AMMO_ENTITIES) {\r
+ return -1;\r
+ }\r
+\r
+ /* Add this index. */\r
+ for (i = 0; i < NUM_AMMO_ENTITIES; i++) {\r
+ if (ammo_entities[i]) continue;\r
+ ammo_entities[i] = entity;\r
+ return i;\r
+ }\r
+\r
+ /* Compiler food. We shouldn't get here. */\r
+ return -1;\r
+}\r
+\r
public OnMapStart() {\r
+ /* Zero out the ammo counts. */\r
+ new i;\r
+ for (i = 0; i < NUM_AMMO_ENTITIES; i++) {\r
+ ammo_entities[i] = 0;\r
+ ammo_counts[i] = 0;\r
+ }\r
}\r
\r
public OnMapEnd() {\r