AMXX-BG.INFO targetex.inc Raw include

targetex.inc

Original include source with line numbers.

Back Download .inc
1 #if defined _targetex_included
2 #endinput
3 #endif
4 #define _targetex_included
5
6 #define TARGETEX_VERSION 1.0
7
8 #include <amxmisc>
9 #include <engine>
10
11 #if !defined MAX_PLAYERS
12 const MAX_PLAYERS = 32
13 #endif
14
15 #if !defined MAX_NAME_LENGTH
16 const MAX_NAME_LENGTH = 32
17 #endif
18
19 #if !defined GetPlayersFlags
20 enum GetPlayersFlags (<<= 1)
21 {
22 GetPlayers_None = 0, // No filter (Default)
23 GetPlayers_ExcludeDead = 1, // Do not include dead clients
24 GetPlayers_ExcludeAlive, // Do not include alive clients
25 GetPlayers_ExcludeBots, // Do not include bots
26 GetPlayers_ExcludeHuman, // Do not include human clients
27 GetPlayers_MatchTeam, // Match with team
28 GetPlayers_MatchNameSubstring, // Match with part of name
29 GetPlayers_CaseInsensitive, // Match case insensitive
30 GetPlayers_ExcludeHLTV, // Do not include HLTV proxies
31 GetPlayers_IncludeConnecting // Include connecting clients
32 };
33
34 stock get_players_ex(players[MAX_PLAYERS] = {}, &num, GetPlayersFlags:flags = GetPlayers_None, const team[] = "")
35 {
36 new strFlags[10];
37 get_flags(_:flags, strFlags, charsmax(strFlags));
38 get_players(players, num, strFlags, team);
39 }
40 #endif
41
42 /**
43 * Selectors used with cmd_targetex()
44 */
45 #define TARGETEX_ARG_AIM "aim"
46 #define TARGETEX_ARG_ALL "all"
47 #define TARGETEX_ARG_ALIVE "alive"
48 #define TARGETEX_ARG_BOTS "bots"
49 #define TARGETEX_ARG_DEAD "dead"
50 #define TARGETEX_ARG_HUMANS "humans"
51 #define TARGETEX_ARG_ME "me"
52 #define TARGETEX_ARG_SPECTATING "spectating"
53 #define TARGETEX_ARG_VIEW "view"
54
55 static const TargetEx_GroupArguments[][] = { TARGETEX_ARG_ALL, TARGETEX_ARG_ALIVE, TARGETEX_ARG_BOTS, TARGETEX_ARG_DEAD, TARGETEX_ARG_HUMANS, TARGETEX_ARG_VIEW };
56 static const TargetEx_NoExcludeArguments[][] = { TARGETEX_ARG_AIM, TARGETEX_ARG_BOTS, TARGETEX_ARG_ME, TARGETEX_ARG_SPECTATING, TARGETEX_ARG_VIEW };
57 static TargetEx_GroupArgsLens[sizeof(TargetEx_GroupArguments)];
58 static TargetEx_NoExcludeArgsLens[sizeof(TargetEx_NoExcludeArguments)];
59
60 /**
61 * Flags used with cmd_targetex()
62 */
63 enum TargetexFlags (<<= 1)
64 {
65 TARGETEX_NONE = 0,
66 TARGETEX_OBEY_IMM_SINGLE = 1,
67 TARGETEX_OBEY_IMM_GROUP,
68 TARGETEX_NO_SELF,
69 TARGETEX_NO_GROUPS,
70 TARGETEX_NO_BOTS,
71 TARGETEX_NO_ALIVE,
72 TARGETEX_NO_DEAD
73 }
74
75 enum TargetExTeamStructure
76 {
77 TARGETEX_TEAM_CODE[5],
78 TARGETEX_TEAM_NAME[10],
79 TARGETEX_TEAM_LEN
80 }
81
82 /**
83 * List of teams used with cmd_targetex()
84 */
85 static TargetEx_Teams[][TargetExTeamStructure] =
86 {
87 { "ct", "CT" },
88 { "t", "TERRORIST" },
89 { "spec", "SPECTATOR" }
90 }
91
92 static TargetEx_TeamStart, TargetEx_TeamEnd;
93
94 /**
95 * Processes a generic target pattern and tries to match it to a client or a
96 * group of clients based on filtering flags and the usage of special arguments.
97 *
98 * @note If no clients were matched an appropriate message is displayed
99 * to the admin.
100 * @note If no group matching symbol is used, the function will use the
101 * cmd_target() stock instead.
102 * @note In order to use the special arguments provided by this function,
103 * the admin must start the <player> argument with the "@" symbol.
104 * @note This is a list of all the available arguments that admins can use:
105 * @aim - targets the player that the admin is aiming at
106 * @all - targets all players
107 * @alive - targets alive players
108 * @bots - targets all bots
109 * @dead - targets dead players
110 * @humans - targets all humans
111 * @me - targets the admin himself
112 * @spectating - targets the client that the admin is spectating
113 * @view - targets all clients in the admin's field of view
114 * @note For arguments that are used to target more than one client,
115 * the admin can also specify a team name after the argument itself,
116 * e.g. @alivect will target all alive counter-terrorists. All the
117 * valid team names and argument codes can be found in the TargetEx_Teams
118 * constant in targetex.inc.
119 * @note When using an argument that targets a group of clients, the admin
120 * can also exclude himself from the command by adding a "!" symbol
121 * right after the "@" one, e.g. @!humans will target all humans
122 * except the admin that used the command.
123 * @note If only one client is matched, the client's name will be copied
124 * in the "name" buffer, otherwise a translated string using one
125 * of the language keys found in cmdtarget.txt will be copied in the
126 * same buffer.
127 *
128 * @param id Client index of admin performing the action
129 * @param arg Target pattern
130 * @param players Array to store the matched clients in
131 * @param name Buffer to store the client name or argument translation
132 * @param len Maximum buffer length
133 * @param flags Optional filtering flags (enum TargetexFlags); valid flags are:
134 * TARGETEX_NONE - no filter (default)
135 * TARGETEX_OBEY_IMM_SINGLE - immunity will be obeyed when using arguments that target a single client
136 * TARGETEX_OBEY_IMM_GROUP - immunity will be obeyed when using arguments that target a group of clients
137 * TARGETEX_NO_SELF - doesn't allow the admin to target himself
138 * TARGETEX_NO_GROUPS - doesn't allow usage of arguments that target a group of clients
139 * TARGETEX_NO_BOTS - doesn't allow targeting bots
140 * TARGETEX_NO_ALIVE - doesn't allow targeting alive clients
141 * TARGETEX_NO_DEAD - doesn't allow targeting dead clients
142 *
143 * @return Number of clients matched
144 */
145 stock cmd_targetex(id, const arg[], players[MAX_PLAYERS], name[], len, TargetexFlags:flags = TARGETEX_OBEY_IMM_SINGLE)
146 {
147 static bool:bDontInit;
148
149 if(!bDontInit)
150 {
151 bDontInit = true;
152
153 new szModName[32];
154 get_modname(szModName, charsmax(szModName));
155
156 if(equal(szModName, "cstrike"))
157 {
158 TargetEx_TeamStart = 0;
159 TargetEx_TeamEnd = 2;
160 }
161
162 TargetEx_TeamEnd++;
163
164 for(new i = TargetEx_TeamStart; i < TargetEx_TeamEnd; i++)
165 {
166 TargetEx_Teams[i][TARGETEX_TEAM_LEN] = strlen(TargetEx_Teams[i][TARGETEX_TEAM_CODE]);
167 }
168
169 for(new i; i < sizeof(TargetEx_GroupArguments); i++)
170 {
171 TargetEx_GroupArgsLens[i] = strlen(TargetEx_GroupArguments[i]);
172 }
173
174 for(new i; i < sizeof(TargetEx_NoExcludeArgsLens); i++)
175 {
176 TargetEx_NoExcludeArgsLens[i] = strlen(TargetEx_NoExcludeArgsLens[i]);
177 }
178
179 register_dictionary("targetex.txt");
180 }
181
182 if(arg[0] == '@')
183 {
184 new bool:bExceptMe = arg[1] == '!', iStartArg = bExceptMe ? 2 : 1;
185 new bool:bIsGroupArg = targetex_is_group_argument(arg[iStartArg]);
186
187 if(bIsGroupArg)
188 {
189 if(flags & TARGETEX_NO_GROUPS)
190 {
191 console_print(id, "%L", id, "TARGETEX_NO_GROUPS");
192 return 0;
193 }
194 }
195
196 if(bExceptMe && targetex_is_no_exclude_argument(arg[iStartArg]))
197 {
198 targetex_cant_exclude(id, arg);
199 return 0;
200 }
201
202 new iPlayers[MAX_PLAYERS], iPnum;
203 new szMatchingString[10], GetPlayersFlags:iMatchingFlags, iMatchedPlayers;
204
205 if(flags & TARGETEX_NO_ALIVE)
206 {
207 iMatchingFlags |= GetPlayers_ExcludeAlive;
208 }
209 else if(flags & TARGETEX_NO_DEAD)
210 {
211 iMatchingFlags |= GetPlayers_ExcludeDead;
212 }
213
214 if(flags & TARGETEX_NO_BOTS)
215 {
216 iMatchingFlags |= GetPlayers_ExcludeBots|GetPlayers_ExcludeHLTV;
217 }
218
219 new szLangKey[32], szSuffix[6], iArgLen = strlen(arg)
220 new iArgLen2 = iArgLen - (bExceptMe ? 1 : 0);
221
222 for(new i = TargetEx_TeamStart; i < TargetEx_TeamEnd; i++)
223 {
224 if(equal(arg[iArgLen - TargetEx_Teams[i][TARGETEX_TEAM_LEN]], TargetEx_Teams[i][TARGETEX_TEAM_CODE]))
225 {
226 szSuffix = "_TEAM";
227 iMatchingFlags |= GetPlayers_MatchTeam;
228 copy(szMatchingString, charsmax(szMatchingString), TargetEx_Teams[i][TARGETEX_TEAM_NAME]);
229
230 if(iArgLen2 == TargetEx_Teams[i][TARGETEX_TEAM_LEN] + 1)
231 {
232 szLangKey = "TARGETEX_ARG_ALL";
233 get_players_ex(iPlayers, iPnum, iMatchingFlags, szMatchingString);
234 goto @AFTER_ARGS;
235 }
236
237 break;
238 }
239 }
240
241 if(equal(arg[iStartArg], TARGETEX_ARG_AIM, 3))
242 {
243 new iTarget, iBody;
244 get_user_aiming(id, iTarget, iBody);
245
246 if(iTarget)
247 {
248 iPlayers[iPnum++] = iTarget;
249 }
250 }
251 else if(equal(arg[iStartArg], TARGETEX_ARG_ALL, 3))
252 {
253 szLangKey = "TARGETEX_ARG_ALL";
254 get_players_ex(iPlayers, iPnum, iMatchingFlags, szMatchingString);
255 }
256 else if(equal(arg[iStartArg], TARGETEX_ARG_ALIVE, 5))
257 {
258 if(flags & TARGETEX_NO_ALIVE)
259 {
260 console_print(id, "%L", id, "TARGETEX_NO_ALIVE")
261 return 0;
262 }
263
264 szLangKey = "TARGETEX_ARG_ALIVE";
265 iMatchingFlags |= GetPlayers_ExcludeDead;
266 get_players_ex(iPlayers, iPnum, iMatchingFlags, szMatchingString);
267 }
268 else if(equal(arg[iStartArg], TARGETEX_ARG_BOTS, 4))
269 {
270 if(flags & TARGETEX_NO_BOTS)
271 {
272 console_print(id, "%L", id, "TARGETEX_NO_BOTS")
273 return 0;
274 }
275
276 szLangKey = "TARGETEX_ARG_BOTS";
277 iMatchingFlags |= GetPlayers_ExcludeHuman;
278 get_players_ex(iPlayers, iPnum, iMatchingFlags, szMatchingString);
279 }
280 else if(equal(arg[iStartArg], TARGETEX_ARG_DEAD, 4))
281 {
282 if(flags & TARGETEX_NO_DEAD)
283 {
284 console_print(id, "%L", id, "TARGETEX_NO_DEAD")
285 return 0;
286 }
287
288 szLangKey = "TARGETEX_ARG_DEAD";
289 iMatchingFlags |= GetPlayers_ExcludeAlive;
290 get_players_ex(iPlayers, iPnum, iMatchingFlags, szMatchingString);
291 }
292 else if(equal(arg[iStartArg], TARGETEX_ARG_HUMANS, 6))
293 {
294 szLangKey = "TARGETEX_ARG_HUMANS";
295 iMatchingFlags |= GetPlayers_ExcludeBots|GetPlayers_ExcludeHLTV;
296 get_players_ex(iPlayers, iPnum, iMatchingFlags, szMatchingString);
297 }
298 else if(equal(arg[iStartArg], TARGETEX_ARG_ME, 2))
299 {
300 iPlayers[iPnum++] = id;
301 }
302 else if(equal(arg[iStartArg], TARGETEX_ARG_SPECTATING, 10))
303 {
304 new iTarget = entity_get_int(id, EV_INT_iuser2);
305
306 if(iTarget)
307 {
308 iPlayers[iPnum++] = iTarget;
309 }
310 }
311 else if(equal(arg[iStartArg], TARGETEX_ARG_VIEW, 4))
312 {
313 new iViewPlayers[MAX_PLAYERS], iViewPnum;
314 get_players_ex(iViewPlayers, iViewPnum, iMatchingFlags, szMatchingString);
315
316 for(new Float:fOrigin[3], iPlayer, i; i < iViewPnum; i++)
317 {
318 iPlayer = iViewPlayers[i];
319 entity_get_vector(iPlayer, EV_VEC_origin, fOrigin);
320
321 if(is_in_viewcone(id, fOrigin, 1))
322 {
323 iPlayers[iPnum++] = iPlayer;
324 }
325 }
326
327 szLangKey = "TARGETEX_ARG_VIEW";
328 }
329
330 @AFTER_ARGS:
331
332 for(new iPlayer, i; i < iPnum; i++)
333 {
334 iPlayer = iPlayers[i];
335
336 if(id == iPlayer)
337 {
338 if(bExceptMe || flags & TARGETEX_NO_SELF)
339 {
340 continue;
341 }
342 }
343 else if(get_user_flags(iPlayer) & ADMIN_IMMUNITY)
344 {
345 if(flags & TARGETEX_OBEY_IMM_GROUP && bIsGroupArg)
346 {
347 continue;
348 }
349
350 if(flags & TARGETEX_OBEY_IMM_SINGLE && !bIsGroupArg)
351 {
352 continue;
353 }
354 }
355
356 players[iMatchedPlayers++] = iPlayer;
357 }
358
359 switch(iMatchedPlayers)
360 {
361 case 0:
362 {
363 console_print(id, "%L", id, "TARGETEX_NO_MATCHES");
364 }
365 case 1:
366 {
367 get_user_name(players[0], name, len);
368 }
369 default:
370 {
371 if(szSuffix[0])
372 {
373 add(szLangKey, charsmax(szLangKey), szSuffix);
374 formatex(name, len, "%L", LANG_PLAYER, szLangKey, szMatchingString);
375 }
376 else
377 {
378 formatex(name, len, "%L", LANG_PLAYER, szLangKey);
379 }
380
381 if(bExceptMe)
382 {
383 format(name, len, "%s %L", name, LANG_PLAYER, "TARGETEX_EXCEPT_HIMSELF");
384 }
385 }
386 }
387
388 return iMatchedPlayers;
389 }
390 else
391 {
392 new iSingleFlags;
393
394 if(flags & TARGETEX_OBEY_IMM_SINGLE)
395 {
396 iSingleFlags |= CMDTARGET_OBEY_IMMUNITY;
397 }
398
399 if(~flags & TARGETEX_NO_SELF)
400 {
401 iSingleFlags |= CMDTARGET_ALLOW_SELF;
402 }
403
404 if(flags & TARGETEX_NO_DEAD)
405 {
406 iSingleFlags |= CMDTARGET_ONLY_ALIVE;
407 }
408
409 if(flags & TARGETEX_NO_BOTS)
410 {
411 iSingleFlags |= CMDTARGET_NO_BOTS;
412 }
413
414 players[0] = cmd_target(id, arg, iSingleFlags);
415
416 if(players[0])
417 {
418 if(flags & TARGETEX_NO_ALIVE && is_user_alive(players[0]))
419 {
420 console_print(id, "%L", id, "TARGETEX_NO_ALIVE");
421 return 0;
422 }
423
424 get_user_name(players[0], name, len);
425 return 1;
426 }
427 }
428
429 return 0;
430 }
431
432 static stock targetex_cant_exclude(id, const arg[])
433 {
434 console_print(id, "%L", id, "TARGETEX_NO_EXCLUDE", arg[2]);
435 }
436
437 /**
438 * Checks whether a specified argument is a team argument.
439 *
440 * @param arg Target pattern
441 *
442 * @return True if it is, false otherwise
443 */
444 stock bool:targetex_is_team_argument(const arg[])
445 {
446 for(new i = TargetEx_TeamStart; i < TargetEx_TeamEnd; i++)
447 {
448 if(equal(arg, TargetEx_Teams[i][TARGETEX_TEAM_CODE], TargetEx_Teams[i][TARGETEX_TEAM_LEN]))
449 {
450 return true;
451 }
452 }
453
454 return false;
455 }
456
457 /**
458 * Checks whether a specified argument is a group argument.
459 *
460 * @param arg Target pattern
461 *
462 * @return True if it is, false otherwise
463 */
464 stock bool:targetex_is_group_argument(const arg[])
465 {
466 for(new i; i < sizeof(TargetEx_GroupArguments); i++)
467 {
468 if(equal(arg, TargetEx_GroupArguments[i], TargetEx_GroupArgsLens[i]))
469 {
470 return true;
471 }
472 }
473
474 return targetex_is_team_argument(arg);
475 }
476
477 /**
478 * Checks whether a specified argument is a type of argument that doesn't
479 * allow the admin to exclude himself.
480 *
481 * @param arg Target pattern
482 *
483 * @return True if it is, false otherwise
484 */
485 stock bool:targetex_is_no_exclude_argument(const arg[])
486 {
487 for(new i; i < sizeof(TargetEx_NoExcludeArguments); i++)
488 {
489 if(equal(arg, TargetEx_NoExcludeArguments[i], TargetEx_NoExcludeArgsLens[i]))
490 {
491 return true;
492 }
493 }
494
495 return false;
496 }