-
Notifications
You must be signed in to change notification settings - Fork 3
/
smartcmd.inc
1346 lines (1174 loc) · 43.5 KB
/
smartcmd.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*******************************************************************************************************************************
SmartCMD a.k.a Improved ZCMD Plus (iZCMD+)
This include is a feature rich version of iZCMD.
Version: 0.3.3 beta (25th December 2017)
GitHub Link: https://github.com/YashasSamaga/SmartCMD
*******************************************************************************************************************************/
#if defined SCMD_INCLUDED
#endinput
#endif
#define SCMD_INCLUDED
#define SCMD_INCLUDED_VMAJOR 0
#define SCMD_INCLUDED_VMINOR 3
#define SCMD_INCLUDED_VPATCH 3
#if !defined _samp_included
#include <a_samp>
#endif
/******************************************************************************************************************************/
#if !defined CMD_DEFAULT_FLAG
#define CMD_DEFAULT_FLAG 0
#endif
#define INVALID_COMMAND_ID (-1)
/* return value to be used in command functions */
#define CMD_SUCCESS 1
#define CMD_FAILURE 0
#if !defined MAX_CLIENT_MSG_LENGTH
#define MAX_CLIENT_MSG_LENGTH (144)
#endif
#if !defined MAX_FUNC_NAME
#define MAX_FUNC_NAME (32)
#endif
// account for the "cmd_" prefix
#define MAX_COMMAND_NAME (MAX_FUNC_NAME - 4)
#if !defined MAX_PUBLIC_FUNCTIONS
#define MAX_PUBLIC_FUNCTIONS (1024)
#endif
#if !defined MAX_COMMANDS
#define MAX_COMMANDS (500)
#endif
#if !defined isnull
#define isnull(%1) ((!(%1[0])) || (((%1[0]) == '\1') && (!(%1[1]))))
#endif
/******************************************************************************************************************************/
/* preprocessor directives to handle command declaration syntax */
/*
CCCM = create command mode
CVARS = create command variables
CCF = create command flags
CCRM = remove
CCID = create command id
*/
const __smartcmd_default_flag = (CMD_DEFAULT_FLAG);
#define cid_%0\32;%1; cid_%0%1
#define flg_%0\32;%1; flg_%0%1
#define flg@%0\32;%1; flg@%0%1
#define alt_%0\32;%1; alt_%0%1
#define alt@%0\32;%1; alt@%0%1
#define tag@%0\32;%1; tag@%0%1
#define cmd_%0\32;%1( cmd_%1(
#define CMD%0:%1(%2) \
forward __smartcmd_CCCM:tag@%1();__smartcmd_CVARS(%0,%1,%2)forward cmd_%1(%2);public cmd_%1(%2)<>return __smartcmd_cmd_handled=0;public cmd_%1(%2)<cmdMode:normal>
#define COMMAND%0:%1(%2) \
CMD%0:%1(%2)
#define command%0(%1,%2,%3,%4) \
CMD%0:%1(%2, %3, %4)
#define cmd%0(%1,%2,%3,%4) \
CMD%0:%1(%2, %3, %4)
#define __smartcmd_CCCM:tag@%0[%1](%9);__smartcmd_CVARS(%9,%9,%2)%9;%9;%9<%9> \
__smartcmd_CCCM:tag@%0();public cmd_%0(%2)<cmdMode:%1>
#define __smartcmd_CVARS(%0,%1,%2) __smartcmd_CCF(%1,%0)__smartcmd_CCRM(%2)__smartcmd_CCID(cid_%1)
#define ALT:%1=%2CMD:%0; \
__smartcmd_CCAV(%1)__smartcmd_CCF(%1,)__smartcmd_CCID(cid_%1)forward cmd_%1(cmdid, playerid, params[]);public cmd_%1(cmdid, playerid, params[])<>return __smartcmd_cmd_handled=0;public cmd_%1(cmdid, playerid, params[])<cmdMode:normal>return __smartcmd_register_alias(GetCommandID(#%0), cmdid);
#define __smartcmd_CCID(%0) \
public stock const %0=-1;
#define __smartcmd_default_flag%9__smartcmd_REMOVE<%1> %1
#define __smartcmd_REMOVE
#define __smartcmd_CCF(%1,%2) \
public flg_%1=(__smartcmd_default_flag __smartcmd_REMOVE%2);stock flg@%1=flg_%1;
#define __smartcmd_CCRM(%2)
#define __smartcmd_CCAV(%1) \
public alt_%1=0; \
stock alt@%1=alt_%1;
/******************************************************************************************************************************/
#if defined OnPlayerCommandReceived
forward OnPlayerCommandReceived(cmdid, playerid, cmdtext[]);
#endif
#if defined OnPlayerCommandPerformed
forward OnPlayerCommandPerformed(cmdid, playerid, cmdtext[], success);
#endif
/******************************************************************************************************************************/
enum __smartcmd_CommandProperties(*=2)
{
__smartcmd_CMD_ENABLED = 1,
__smartcmd_CMD_HAS_ALTERNATE,
__smartcmd_CMD_IS_ALTERNATE
}
static __smartcmd_CommandProperties:izcmd_cmd_properties[MAX_COMMANDS];
#define __IsCommandPropertySet(%0,%1) ((izcmd_cmd_properties[%0]) & (%1))
#define __SetCommandProperty(%0,%1) ((izcmd_cmd_properties[%0]) |= (%1))
#define __UnsetCommandProperty(%0,%1) ((izcmd_cmd_properties[%0]) &= ~(%1))
/******************************************************************************************************************************/
//Internal Arrays
static __smartcmd_fidx_pcid_map[MAX_PUBLIC_FUNCTIONS] = { INVALID_COMMAND_ID, INVALID_COMMAND_ID, INVALID_COMMAND_ID, ... }; //cmdid to be used for the given funcidx in OnPlayerCommandText
static __smartcmd_cid_pfidx_map[MAX_COMMANDS] = { -1, -1, -1, ... }; //pointing command function
static __smartcmd_cid_pid_map[MAX_COMMANDS] = { INVALID_COMMAND_ID, INVALID_COMMAND_ID, INVALID_COMMAND_ID, ... }; //pointing cmdid
//Constant Arrays (must not be modified)
static __const_smartcmd_funcname[MAX_COMMANDS][MAX_FUNC_NAME];
static __const_smartcmd_fidx_ocid_map[MAX_PUBLIC_FUNCTIONS] = { INVALID_COMMAND_ID, INVALID_COMMAND_ID, INVALID_COMMAND_ID, ... };
static __const_smartcmd_cid_ofidx_map[MAX_COMMANDS] = { -1, -1, -1, ... }; //original command function
//Per-Command Properties
static __smartcmd_pfaddress[MAX_COMMANDS] = { -1, -1, -1, ... };
static __smartcmd_cflags[MAX_COMMANDS][1];
//General Command Statstics
static __smartcmd_cmd_total_count = 0;
static __smartcmd_cmd_enabled_count = 0;
//Internal Variables
static __smartcmd_offsetDAT, __smartcmd_offsetPFT, __smartcmd_offsetNFT, __smartcmd_offsetPVT, __smartcmd_offsetTAGS, __smartcmd_number_of_publics, __smartcmd_number_of_pubvars;
//Addtitional Support Variables (used internally)
new __smartcmd_cmd_handled = 1;
/******************************************************************************************************************************/
static stock __smartcmd_dummy() < > return 0;
static stock __smartcmd_dummy() < cmdMode:normal > return 0;
static __smartcmd_LoadString(addr, str[])
{
new chr, j;
do
{
#emit LREF.S.pri addr
#emit STOR.S.pri chr
str[j++] = chr = (chr & 0xFF);
#emit INC.S addr
} while (chr != EOS);
}
static __smartcmd_init()
{
new addr, tmp, cmd_name[MAX_FUNC_NAME] = "cmd_", bool:crash = false;
state cmdMode:normal;
#emit LCTRL 1
#emit NEG
#emit STOR.pri __smartcmd_offsetDAT
#emit ADD.C 32
#emit STOR.S.pri addr
#emit LREF.S.pri addr
#emit LOAD.S.alt addr
#emit ADD
#emit CONST.alt 32
#emit SUB
#emit STOR.pri __smartcmd_offsetPFT
#emit LOAD.pri __smartcmd_offsetDAT
#emit ADD.C 36
#emit STOR.S.pri addr
#emit LREF.S.pri addr
#emit LOAD.S.alt addr
#emit ADD
#emit CONST.alt 36
#emit SUB
#emit STOR.pri __smartcmd_offsetNFT
#emit LOAD.pri __smartcmd_offsetDAT
#emit ADD.C 44
#emit STOR.S.pri addr
#emit LREF.S.pri addr
#emit LOAD.S.alt addr
#emit ADD
#emit CONST.alt 44
#emit SUB
#emit STOR.pri __smartcmd_offsetPVT
#emit LOAD.pri __smartcmd_offsetDAT
#emit ADD.C 48
#emit STOR.S.pri addr
#emit LREF.S.pri addr
#emit LOAD.S.alt addr
#emit ADD
#emit CONST.alt 48
#emit SUB
#emit STOR.pri __smartcmd_offsetTAGS
__smartcmd_number_of_publics = ((__smartcmd_offsetNFT - __smartcmd_offsetPFT) >>> 3);
__smartcmd_number_of_pubvars = ((__smartcmd_offsetTAGS - __smartcmd_offsetPVT) >>> 3);
for (new pubfunc_idx = 0; pubfunc_idx < __smartcmd_number_of_publics; pubfunc_idx++)
{
if (pubfunc_idx == MAX_PUBLIC_FUNCTIONS)
{
printf("[ERROR] MAX_PUBLIC_FUNCTIONS (Current Value: %d) must be set to %d or higher.", MAX_PUBLIC_FUNCTIONS, __smartcmd_number_of_publics);
print("[WARNING] All commands may not work as expected.");
crash = true;
break;
}
addr = (pubfunc_idx << 3) + __smartcmd_offsetPFT + 4;
#emit LREF.S.pri addr
#emit LOAD.alt __smartcmd_offsetDAT
#emit ADD
#emit STOR.S.pri addr
#emit LREF.S.pri addr
#emit STOR.S.pri tmp
if (tmp != ((('_') << 24) | (('d') << 16) | (('m') << 8) | ('c'))) continue; {}
strcat(__const_smartcmd_funcname[__smartcmd_cmd_total_count], "cmd_", MAX_FUNC_NAME);
#emit LOAD.S.pri addr
#emit ADD.C 4
#emit STOR.S.pri addr
__smartcmd_LoadString(addr, __const_smartcmd_funcname[__smartcmd_cmd_total_count][4]);
#emit LOAD.pri __smartcmd_offsetPFT
#emit LOAD.S.alt pubfunc_idx
#emit SHL.C.alt 3
#emit ADD
#emit STOR.S.pri addr
#emit LREF.S.pri addr
#emit STOR.S.pri addr
__const_smartcmd_fidx_ocid_map[pubfunc_idx] = __smartcmd_fidx_pcid_map[pubfunc_idx] = __smartcmd_cmd_total_count;
__const_smartcmd_cid_ofidx_map[__smartcmd_cmd_total_count] = __smartcmd_cid_pfidx_map[__smartcmd_cmd_total_count] = pubfunc_idx;
__SetCommandProperty(__smartcmd_cmd_total_count, __smartcmd_CMD_ENABLED);
__smartcmd_pfaddress[__smartcmd_cmd_total_count] = addr;
__smartcmd_cmd_total_count++;
__smartcmd_cmd_enabled_count++;
if (__smartcmd_cmd_total_count == MAX_COMMANDS)
{
printf("[ERROR] MAX_COMMANDS (Current Value: %d) must be set to larger number.", __smartcmd_cmd_total_count);
print("[WARNING] All commands may not work as expected.");
crash = true;
break;
}
}
for (new pubvar_idx = 0; pubvar_idx < __smartcmd_number_of_pubvars; pubvar_idx++)
{
addr = (pubvar_idx << 3) + __smartcmd_offsetPVT + 4;
#emit LREF.S.pri addr
#emit LOAD.alt __smartcmd_offsetDAT
#emit ADD
#emit STOR.S.pri addr
#emit LREF.S.pri addr
#emit STOR.S.pri tmp
if (tmp == ((('_') << 24) | (('g') << 16) | (('l') << 8) | ('f')))
{
#emit LOAD.S.pri addr
#emit ADD.C 4
#emit STOR.S.pri addr
__smartcmd_LoadString(addr, cmd_name[4]);
new cmd_idx = funcidx(cmd_name);
if (cmd_idx == -1) break;
if (cmd_idx >= MAX_PUBLIC_FUNCTIONS) break; {}
#emit LOAD.pri __smartcmd_offsetPVT
#emit LOAD.S.alt pubvar_idx
#emit SHL.C.alt 3
#emit ADD
#emit STOR.S.pri addr
#emit LREF.S.pri addr
#emit STOR.S.pri addr
#emit LOAD.I
#emit STOR.S.pri tmp
new x, n;
#emit CONST.alt __const_smartcmd_fidx_ocid_map
#emit LOAD.S.pri cmd_idx
#emit LIDX
#emit CONST.alt __smartcmd_cflags
#emit IDXADDR
#emit STOR.S.pri x
n = addr - x;
#emit LOAD.S.alt x
#emit LOAD.S.pri n
#emit STOR.I
}
else if (tmp == ((('_') << 24) + (('t') << 16) + (('l') << 8) + ('a')))
{
#emit LOAD.S.pri addr
#emit ADD.C 4
#emit STOR.S.pri addr
__smartcmd_LoadString(addr, cmd_name[4]);
new cmd_idx = funcidx(cmd_name);
if (cmd_idx == -1) break;
if (cmd_idx >= MAX_PUBLIC_FUNCTIONS) break;
new cmdid = __const_smartcmd_fidx_ocid_map[cmd_idx];
#emit PUSH.S cmd_name //doesn't matter what is pushed
#emit PUSH.C 0
#emit PUSH.S cmdid
#emit PUSH.C 12
#emit LCTRL 6
#emit ADD.C 40
#emit PUSH.pri
#emit CONST.alt __smartcmd_pfaddress
#emit LOAD.S.pri cmdid
#emit LIDX
#emit SCTRL 6
}
else if (tmp == ((('_') << 24) + (('d') << 16) + (('i') << 8) + ('c')))
{
#emit LOAD.S.pri addr
#emit ADD.C 4
#emit STOR.S.pri addr
__smartcmd_LoadString(addr, cmd_name[4]);
new cmd_idx = funcidx(cmd_name);
if (cmd_idx == -1) break;
if (cmd_idx >= MAX_PUBLIC_FUNCTIONS) break; {}
#emit LOAD.pri __smartcmd_offsetPVT
#emit LOAD.S.alt pubvar_idx
#emit SHL.C.alt 3
#emit ADD
#emit STOR.S.pri addr
#emit LREF.S.pri addr
#emit STOR.S.pri addr
#emit CONST.alt __const_smartcmd_fidx_ocid_map
#emit LOAD.S.pri cmd_idx
#emit LIDX
#emit LOAD.S.alt addr
#emit STOR.I
}
}
if (crash)
{
new x = MAX_COMMANDS;
return __smartcmd_pfaddress[x];
}
return 1;
}
/******************************************************************************************************************************/
#if defined FILTERSCRIPT
public OnFilterScriptInit()
{
__smartcmd_init();
#if defined izcmd_OnFilterScriptInit
return izcmd_OnFilterScriptInit();
#else
return 1;
#endif
}
#if defined _ALS_OnFilterScriptInit
#undef OnFilterScriptInit
#else
#define _ALS_OnFilterScriptInit
#endif
#define OnFilterScriptInit izcmd_OnFilterScriptInit
#if defined OnFilterScriptInit
forward OnFilterScriptInit();
#endif
#else
public OnGameModeInit()
{
__smartcmd_init();
#if defined izcmd_OnGameModeInit
return izcmd_OnGameModeInit();
#else
return 1;
#endif
}
#if defined _ALS_OnGameModeInit
#undef OnGameModeInit
#else
#define _ALS_OnGameModeInit
#endif
#define OnGameModeInit izcmd_OnGameModeInit
#if defined izcmd_OnGameModeInit
forward izcmd_OnGameModeInit();
#endif
#endif
/******************************************************************************************************************************/
public OnPlayerCommandText(playerid, cmdtext[])
{
static prefix[4] = { 'c', 'm', 'd', '_' }, funcname[MAX_CLIENT_MSG_LENGTH - 4];
new cmdid, tmp, addr, faddr;
state cmdMode:normal;
#emit CONST.pri funcname
#emit STOR.S.pri faddr
#emit LOAD.S.pri cmdtext
#emit ADD.C 4
#emit STOR.S.pri addr
#emit LOAD.I
#emit STOR.S.pri tmp
while (tmp > ' ')
{
#if !defined IZCMD_ENABLE_CASE_SENSITIVITY
if ('A' <= tmp <= 'Z')
{
#emit LOAD.S.pri tmp
#emit CONST.alt 32
#emit OR
#emit LOAD.S.alt faddr
#emit STOR.I
}
else
#endif
{
#emit LOAD.S.alt faddr
#emit LOAD.S.pri tmp
#emit STOR.I
}
#emit LOAD.S.pri faddr
#emit ADD.C 4
#emit STOR.S.pri faddr
#emit LOAD.S.pri addr
#emit ADD.C 4
#emit STOR.S.pri addr
#emit LOAD.I
#emit STOR.S.pri tmp
}
#emit LOAD.S.alt faddr
#emit ZERO.pri
#emit STOR.I
while (tmp == ' ')
{
#emit LOAD.S.pri addr
#emit ADD.C 4
#emit STOR.S.pri addr
#emit LOAD.I
#emit STOR.S.pri tmp
}
if ((tmp = funcidx(prefix)) != -1)
{
if ((cmdid = __smartcmd_fidx_pcid_map[tmp]) != INVALID_COMMAND_ID && __IsCommandPropertySet(cmdid, __smartcmd_CMD_ENABLED))
{
#if defined OnPlayerCommandReceived
if (!OnPlayerCommandReceived(cmdid, playerid, cmdtext)) return 1; {}
#endif
#emit PUSH.S addr
#emit PUSH.S playerid
#emit PUSH.S cmdid
#emit PUSH.C 12
#emit LCTRL 6
#emit ADD.C 40
#emit PUSH.pri
#emit CONST.alt __smartcmd_pfaddress
#emit LOAD.S.pri cmdid
#emit LIDX
#emit SCTRL 6
#emit STOR.S.pri tmp
#if defined OnPlayerCommandPerformed
return OnPlayerCommandPerformed(cmdid, playerid, cmdtext, tmp);
#else
return tmp;
#endif
}
}
#if defined OnPlayerCommandReceived
if (!OnPlayerCommandReceived(INVALID_COMMAND_ID, playerid, cmdtext)) return 1;
#endif
#if defined OnPlayerCommandPerformed
return OnPlayerCommandPerformed(INVALID_COMMAND_ID, playerid, cmdtext, 0);
#else
return 0;
#endif
}
/******************************************************************************************************************************/
/*
native DoesCommandExist(cmdid)
native GetCommandID(const cmd[])
native GetCommandName(cmdid, cmd[], len = sizeof(cmd))
native GetAlternateCommands(cmdid, cmdidlist[])
native IsCommandAlternate(cmdid)
native GetCommandFunctionID(cmdid)
native GetPointingCommandFunctionID(cmdid)
native GetPointingCommandID(cmdid)
native GetCommandFunctionName(cmdid, dest[], len = sizeof(dest))
native GetEnabledCommandCount()
native GetDisabledCommandCount()
native GetTotalCommandCount()
native EnableCommand(cmdid)
native DisableCommand(cmdid)
native IsCommandEnabled(cmdid)
native SetCommandFlags(cmdid, flags)
native GetCommandFlags(cmdid)
native SetPointingCommandIDToSelf(cmdid)
native ReassignCommandFunction(cmdid, const funcname[], bool:updateCID = false, bool:updatePFT = false)
native EmulateCommandEx(cmdid, playerid, params[])
native EmulateCommand(playerid, cmdtext[])
native ExecuteCommand(const cmd[], command_mode, playerid, &success, params[]="")
*/
/*******************************************************************************************************************************
<summary>DoesCommandExist</summary>
<para>checks if a command exists</para>
<param name="cmd">command name</param>
<returns>
Returns true if the command exists
</returns>
<example>
<code>
if(DoesCommandExist("ban"))
printf("Ban command exists");
</code>
</example>
*******************************************************************************************************************************/
#define DoesCommandExist(%0) (GetCommandID(%0) != INVALID_COMMAND_ID)
/*******************************************************************************************************************************
<summary>GetCommandID</summary>
<para>Finds command id from the given commmand name</para>
<param name="cmd">command name</param>
<returns>
the command id or INVALID_COMMAND_ID if the command does not exist.
</returns>
<remarks>
The command name passed must have the command name not the command function name. For example, if you have a ban command
the command name is "ban" whereas the function name is "cmd_ban". You must pass "ban" to this function to obtain ban
command's command id.
If you are already aware of the command name during compile time, you can obtain the command idby directly referncing
the variable whose identifier is the command name prefixed with "cid_".
Please do not attempt to modify the value of variables prefixed with "cid_". The variable becomes unusable if you modify
but will not affect the command processor and other commands.
</remarks>
<example>
<code>
new id = GetCommandID("ban"); //is same as "new id = cid_ban;"
</code>
</example>
*******************************************************************************************************************************/
stock GetCommandID(const cmd[])
{
static funcname[MAX_FUNC_NAME] = "cmd_";
funcname[4] = 0;
strcat(funcname, cmd);
new idx = funcidx(funcname);
if (idx == -1)
return INVALID_COMMAND_ID;
return __const_smartcmd_fidx_ocid_map[idx];
}
/*******************************************************************************************************************************
<summary>GetCommandName</summary>
<para>Gets a command name in unpacked format</para>
<param name="cmdid">command id whose name is required</param>
<param name="cmd">destination array</param>
<param name="len">maximum length of cmd</param>
<returns>
1 on success and 0 on failure (invalid command id was passed).
</returns>
<example>
<code>
new str[MAX_COMMAND_NAME];
GetCommandName(cmdid, str);
</code>
</example>
*******************************************************************************************************************************/
stock GetCommandName(cmdid, cmd[], len = sizeof(cmd))
{
if (!(0 <= cmdid < __smartcmd_cmd_total_count)) return 0;
cmd[0] = 0;
strcat(cmd, __const_smartcmd_funcname[cmdid][4], len);
return 1;
}
/*******************************************************************************************************************************
<summary>GetAlternateCommands</summary>
<para>Gets a list of alternate command names associated with the given command</para>
<param name="cmdid">command id</param>
<param name="cmdidlist">array where the alternate command ids must be stored</param>
<param name="cmdidlist_len">length of 'cmdidlist' array</param>
<returns>
the number of alternate commands or INVALID_COMMAND_ID in case cmdid passed has an invalid id.
</returns>
<remarks>
The function does not do boundary checks on the cmdidlist array. It is required that the array passed is sufficiently large.
</remarks>
<example>
<code>
new acmdlist[5], cmdname[MAX_COMMAND_NAME];
new count = GetAlternateCommands(GetCommandID("spectate"), acmdlist);
new helpstr[200] = "Alternate commands for spectate:";
for(new i = 0; i < count; i++)
{
GetCommandName(acmdlist[i], cmdname);
strcat(helpstr, cmdname);
strcat(helpstr, " ");
}
</code>
</example>
*******************************************************************************************************************************/
stock GetAlternateCommands(cmdid, cmdidlist[], cmdidlist_len = sizeof(cmdidlist))
{
if (!(0 <= cmdid < __smartcmd_cmd_total_count)) return INVALID_COMMAND_ID;
new count = 0;
if (__IsCommandPropertySet(cmdid, __smartcmd_CMD_HAS_ALTERNATE))
{
for (new id = 0; id < __smartcmd_cmd_total_count; id++)
{
if (id == cmdid) continue;
if (__smartcmd_cid_pid_map[id] == cmdid)
{
cmdidlist[count++] = id;
if(count == cmdidlist_len)
break;
}
}
}
return count;
}
/*******************************************************************************************************************************
<summary>IsCommandAlternate</summary>
<para>checks if the given command is an alternate command</para>
<param name="cmdid">command id</param>
<returns>
true(false) if the command is an(not an) alternate command or INVALID_COMMAND_ID if the command id passed is invalid.
</returns>
<remarks>
The location where the file should be created should be relative to the scriptfiles folder
</remarks>
<example>
<code>
for(new i = 0, j = GetTotalCommandCount(); i < j; i++)
{
if(i == cmdid) continue;
if(IsCommandAlternate(i)) continue;
new cmd[28];
GetCommandName(i, cmd);
strcat(str, cmd);
strcat(str, " ");
}
</code>
</example>
*******************************************************************************************************************************/
stock IsCommandAlternate(cmdid)
{
if (!(0 <= cmdid < __smartcmd_cmd_total_count)) return INVALID_COMMAND_ID;
return !!(__IsCommandPropertySet(cmdid, __smartcmd_CMD_IS_ALTERNATE));
}
/*******************************************************************************************************************************
<summary>GetCommandFunctionID</summary>
<para>returns the original function (check remarks) index of the given command. Identical to funcidx.</para>
<param name="cmdid">command id</param>
<returns>
INVALID_COMMAND_ID if the given command id is invalid else returns the function index.
</returns>
<remarks>
original function - the function which is associated with the command when the server starts
pointing function - the function which is executed when the command is used
</remarks>
<example>
<code>
if(GetCommandFunctionID(GetCommandID("ban")) != funcidx("cmd_ban")) print("Logic does not work in this world");
</code>
</example>
*******************************************************************************************************************************/
stock GetCommandFunctionID(cmdid)
{
if (!(0 <= cmdid < __smartcmd_cmd_total_count)) return INVALID_COMMAND_ID;
return __const_smartcmd_cid_ofidx_map[cmdid];
}
/*******************************************************************************************************************************
<summary>GetPointingCommandFunctionID</summary>
<para>returns the pointing function (check remarks) index of the given command.</para>
<param name="cmdid">command id</param>
<returns>
INVALID_COMMAND_ID if the given command id is invalid else returns the function index.
</returns>
<remarks>
original function - the function which is associated with the command when the server starts
pointing function - the function which is executed when the command is used
</remarks>
<example>
<code>
//spec is an alternate command for the command spectate
if(GetPointingCommandFunctionID(spec_cmdid) == GetCommandFunctionID(spectate_cmdid)) print("All iz well.");
</code>
</example>
*******************************************************************************************************************************/
stock GetPointingCommandFunctionID(cmdid)
{
if (!(0 <= cmdid < __smartcmd_cmd_total_count)) return INVALID_COMMAND_ID;
return __smartcmd_cid_pfidx_map[cmdid];
}
/*******************************************************************************************************************************
<summary>GetPointingCommandID</summary>
<para>finds the command to which the given command points to</para>
<param name="cmdid">command id</param>
<returns>
pointing command id
</returns>
<remarks>
pointing command - the command which is executed when the command is used.
Reassigning a command to a command function of another command without setting the updateCID parameter to true will NOT
make the reassigned command to point to the new command. It only calls the command function. The command id of the
reassigned command will be passed to the command function.
In case of alternate commands, the command id of the original command is passed to the command function. In other words,
your command can never know if the player used the original command directly or used an alternate command.
</remarks>
<example>
<code>
//spec is an alternate command for the command spectate
if(GetPointingCommandID(spec_cmdid) == spectate_cmdid) print("All iz well.");
</code>
</example>
*******************************************************************************************************************************/
stock GetPointingCommandID(cmdid)
{
if (!(0 <= cmdid < __smartcmd_cmd_total_count)) return INVALID_COMMAND_ID;
return __smartcmd_cid_pid_map[cmdid];
}
/*******************************************************************************************************************************
<summary>GetCommandFunctionName</summary>
<para>gets the command name in its function name form</para>
<param name="cmdid">command id</param>
<param name="dest">destination array where the function name has to be stored</param>
<param name="len">size of the destination array</param>
<returns>
1 on success or INVALID_COMMAND_ID on if the given command id is invalid.
</returns>
<example>
<code>
//Avoid using CallLocalFunction to call commands manually. Use EmulateCommand(Ex) for the same.
CallLocalFunction(GetCommandFunctionName("ban"), "iis", GetCommandID("ban"), playerid, "test ban");
</code>
</example>
*******************************************************************************************************************************/
stock GetCommandFunctionName(cmdid, dest[], len = sizeof(dest))
{
if (!(0 <= cmdid < __smartcmd_cmd_total_count)) return INVALID_COMMAND_ID;
dest[0] = 0;
strcat(dest, "cmd_", len);
GetCommandName(cmdid, dest[4], len - 4);
return 1;
}
/*******************************************************************************************************************************
<summary>GetEnabledCommandCount</summary>
<para>gets the number of enabled commands</para>
<returns>
number of enabled commands
</returns>
<example>
<code>
printf("Number of commands enabled: %d", GetEnabledCommandCount());
</code>
</example>
*******************************************************************************************************************************/
stock GetEnabledCommandCount()
{
return __smartcmd_cmd_enabled_count;
}
/*******************************************************************************************************************************
<summary>GetDisabledCommandCount</summary>
<para>gets the number of disabled(deleted) commands</para>
<returns>
number of disabled commands
</returns>
<example>
<code>
printf("Number of commands disabled: %d", GetDisabledCommandCount());
</code>
</example>
*******************************************************************************************************************************/
stock GetDisabledCommandCount()
{
return __smartcmd_cmd_total_count - __smartcmd_cmd_enabled_count;
}
/*******************************************************************************************************************************
<summary>GetTotalCommandCount</summary>
<para>gets total number of commands in the script</para>
<returns>
number of commands in the script
</returns>
<example>
<code>
printf("Total number of commands: %d", GetTotalCommandCount());
</code>
</example>
*******************************************************************************************************************************/
stock GetTotalCommandCount()
{
return __smartcmd_cmd_total_count;
}
/*******************************************************************************************************************************
<summary>EnableCommand</summary>
<para>Enables(Undelete) a command if it was disabled(deleted)</para>
<param name="cmd">cmdid</param>
<returns>
INVALID_COMMAND_ID if the given command id is invalid.
0 if the command was already enabled.
1 if the command was enabled.
</returns>
<example>
<code>
EnableCommand(cid_event_join);
</code>
</example>
*******************************************************************************************************************************/
stock EnableCommand(cmdid)
{
if (!(0 <= cmdid < __smartcmd_cmd_total_count)) return INVALID_COMMAND_ID;
if (__IsCommandPropertySet(cmdid, __smartcmd_CMD_ENABLED)) return 0;
__SetCommandProperty(cmdid, __smartcmd_CMD_ENABLED);
__smartcmd_cmd_enabled_count++;
return 1;
}
/*******************************************************************************************************************************
<summary>EnableCommand</summary>
<para>Disables(delete) a command if it was enabled</para>
<param name="cmd">cmdid</param>
<returns>
INVALID_COMMAND_ID if the given command id is invalid.
0 if the command was already disabled.
1 if the command was disabled.
</returns>
<example>
<code>
DisableCommand(cid_event_join);
</code>
</example>
*******************************************************************************************************************************/
stock DisableCommand(cmdid)
{
if (!(0 <= cmdid < __smartcmd_cmd_total_count)) return INVALID_COMMAND_ID;
if (!__IsCommandPropertySet(cmdid, __smartcmd_CMD_ENABLED)) return 0;
__UnsetCommandProperty(cmdid, __smartcmd_CMD_ENABLED);
__smartcmd_cmd_enabled_count--;
return 1;
}
/*******************************************************************************************************************************
<summary>IsCommandEnabled</summary>
<para>checks if a command is enabled</para>
<param name="cmdid">command id</param>
<returns>
true if the command is enabled or INVALID_COMMAND_ID If the given command id is invalid.
</returns>
<example>
<code>
if(IsCommandEnabled(cid_event_join)) return SendClientMessage(playerid, RED, "An event is in progress.");
</code>
</example>
*******************************************************************************************************************************/
stock IsCommandEnabled(cmdid)
{
if (!(0 <= cmdid < __smartcmd_cmd_total_count)) return INVALID_COMMAND_ID;
return !!(__IsCommandPropertySet(cmdid, __smartcmd_CMD_ENABLED));
}
/*******************************************************************************************************************************
<summary>SetCommandFlags</summary>
<para>sets a command's flags</para>
<param name="cmdid">command id</param>
<param name="flags">new flags</param>
<returns>
1 on success and INVALID_COMMAND_ID if the given command id is invalid.
</returns>
<remarks>
If you are already aware of the command's name, you can directly modify the flag variable. The flag variable identifier
is the command name prefixed with 'flg_'. For example, the ban command's flags are stored in 'flg_ban'. Directly accessing
the flag variable is faster than using this function.
</remarks>
<example>
<code>
SetCommandFlags(cmdid, ADMIN_COMMAND);
SetCommandFlags(cid_ban, ADMIN_COMMAND); //is functionally equivalent to doing "flg_ban = ADMIN_COMMAND;"
</code>
</example>
*******************************************************************************************************************************/
stock SetCommandFlags(cmdid, flags)
{
if (!(0 <= cmdid < __smartcmd_cmd_total_count)) return INVALID_COMMAND_ID;
__smartcmd_cflags[cmdid][0] = flags;
return 1;
}
/*******************************************************************************************************************************
<summary>GetCommandFlags</summary>
<para>gets the given command's flags</para>
<param name="cmdid">command id</param>
<returns>
the command's flags or INVALID_COMMAND_ID if the command id passed is invalid.
</returns>
<remarks>
It is possible that your flags might evaluate to INVALID_COMMAND_ID and hence GetCommandFlags might pretend to be returning
INVALID_COMMAND_ID for a valid command id.
The best way to deal with it is to ensure that invalid command id would never be passed.
</remarks>
<example>
<code>
new flags = GetCommandFlags(cid_ban);
new flags = GetCommandFlags(GetCommandID("ban"); //is functionally equivalent to doing "new flags = flg_ban;"
</code>
</example>
*******************************************************************************************************************************/
stock GetCommandFlags(cmdid)
{
if (!(0 <= cmdid < __smartcmd_cmd_total_count)) return INVALID_COMMAND_ID;
#emit CONST.alt __smartcmd_cflags
#emit LOAD.S.pri cmdid
#emit LIDX
#emit LOAD.I
#emit RETN
return __smartcmd_cflags[cmdid][0];
}