summaryrefslogtreecommitdiff
path: root/sourcemod-1.5-dev
diff options
context:
space:
mode:
Diffstat (limited to 'sourcemod-1.5-dev')
-rw-r--r--sourcemod-1.5-dev/GPLv2.txt339
-rw-r--r--sourcemod-1.5-dev/GPLv3.txt674
-rw-r--r--sourcemod-1.5-dev/LICENSE.txt39
-rw-r--r--sourcemod-1.5-dev/scripting/compile.exebin0 -> 113664 bytes
-rw-r--r--sourcemod-1.5-dev/scripting/include/admin.inc631
-rw-r--r--sourcemod-1.5-dev/scripting/include/adminmenu.inc154
-rw-r--r--sourcemod-1.5-dev/scripting/include/adt.inc40
-rw-r--r--sourcemod-1.5-dev/scripting/include/adt_array.inc283
-rw-r--r--sourcemod-1.5-dev/scripting/include/adt_stack.inc154
-rw-r--r--sourcemod-1.5-dev/scripting/include/adt_trie.inc156
-rw-r--r--sourcemod-1.5-dev/scripting/include/banning.inc157
-rw-r--r--sourcemod-1.5-dev/scripting/include/basecomm.inc109
-rw-r--r--sourcemod-1.5-dev/scripting/include/bitbuffer.inc325
-rw-r--r--sourcemod-1.5-dev/scripting/include/clientprefs.inc282
-rw-r--r--sourcemod-1.5-dev/scripting/include/clients.inc778
-rw-r--r--sourcemod-1.5-dev/scripting/include/commandfilters.inc165
-rw-r--r--sourcemod-1.5-dev/scripting/include/console.inc971
-rw-r--r--sourcemod-1.5-dev/scripting/include/core.inc237
-rw-r--r--sourcemod-1.5-dev/scripting/include/cstrike.inc422
-rw-r--r--sourcemod-1.5-dev/scripting/include/datapack.inc142
-rw-r--r--sourcemod-1.5-dev/scripting/include/dbi.inc762
-rw-r--r--sourcemod-1.5-dev/scripting/include/entity.inc738
-rw-r--r--sourcemod-1.5-dev/scripting/include/entity_prop_stocks.inc559
-rw-r--r--sourcemod-1.5-dev/scripting/include/events.inc257
-rw-r--r--sourcemod-1.5-dev/scripting/include/files.inc411
-rw-r--r--sourcemod-1.5-dev/scripting/include/float.inc437
-rw-r--r--sourcemod-1.5-dev/scripting/include/functions.inc511
-rw-r--r--sourcemod-1.5-dev/scripting/include/geoip.inc102
-rw-r--r--sourcemod-1.5-dev/scripting/include/halflife.inc625
-rw-r--r--sourcemod-1.5-dev/scripting/include/handles.inc96
-rw-r--r--sourcemod-1.5-dev/scripting/include/helpers.inc293
-rw-r--r--sourcemod-1.5-dev/scripting/include/keyvalues.inc429
-rw-r--r--sourcemod-1.5-dev/scripting/include/lang.inc121
-rw-r--r--sourcemod-1.5-dev/scripting/include/logging.inc142
-rw-r--r--sourcemod-1.5-dev/scripting/include/mapchooser.inc132
-rw-r--r--sourcemod-1.5-dev/scripting/include/menus.inc827
-rw-r--r--sourcemod-1.5-dev/scripting/include/morecolors.inc674
-rw-r--r--sourcemod-1.5-dev/scripting/include/nextmap.inc84
-rw-r--r--sourcemod-1.5-dev/scripting/include/profiler.inc77
-rw-r--r--sourcemod-1.5-dev/scripting/include/protobuf.inc368
-rw-r--r--sourcemod-1.5-dev/scripting/include/regex.inc186
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdkhooks.inc394
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools.inc232
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_client.inc52
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_engine.inc69
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_entinput.inc116
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_entoutput.inc91
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_functions.inc346
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_gamerules.inc202
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_hooks.inc59
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_sound.inc450
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_stocks.inc76
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_stringtables.inc180
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_tempents.inc228
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_tempents_stocks.inc458
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_trace.inc374
-rw-r--r--sourcemod-1.5-dev/scripting/include/sdktools_voice.inc124
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib.inc32
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/arrays.inc158
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/clients.inc3121
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/colors.inc528
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/concommands.inc47
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/convars.inc72
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/crypt.inc630
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/debug.inc30
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/dynarrays.inc24
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/edicts.inc127
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/effects.inc743
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/entities.inc2153
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/files.inc458
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/game.inc58
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/general.inc251
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/math.inc344
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/menus.inc38
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/server.inc135
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/sql.inc108
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/strings.inc229
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/teams.inc318
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/vehicles.inc141
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/weapons.inc399
-rw-r--r--sourcemod-1.5-dev/scripting/include/smlib/world.inc17
-rw-r--r--sourcemod-1.5-dev/scripting/include/sorting.inc176
-rw-r--r--sourcemod-1.5-dev/scripting/include/sourcemod.inc682
-rw-r--r--sourcemod-1.5-dev/scripting/include/string.inc559
-rw-r--r--sourcemod-1.5-dev/scripting/include/testing.inc72
-rw-r--r--sourcemod-1.5-dev/scripting/include/textparse.inc203
-rw-r--r--sourcemod-1.5-dev/scripting/include/tf2.inc440
-rw-r--r--sourcemod-1.5-dev/scripting/include/tf2_stocks.inc548
-rw-r--r--sourcemod-1.5-dev/scripting/include/timers.inc211
-rw-r--r--sourcemod-1.5-dev/scripting/include/topmenus.inc314
-rw-r--r--sourcemod-1.5-dev/scripting/include/usermessages.inc218
-rw-r--r--sourcemod-1.5-dev/scripting/include/vector.inc188
-rw-r--r--sourcemod-1.5-dev/scripting/include/version.inc49
-rw-r--r--sourcemod-1.5-dev/scripting/include/version_auto.inc15
-rw-r--r--sourcemod-1.5-dev/scripting/ljstats.smxbin0 -> 62004 bytes
-rw-r--r--sourcemod-1.5-dev/scripting/ljstats.sp4375
-rw-r--r--sourcemod-1.5-dev/scripting/spcomp.exebin0 -> 384000 bytes
97 files changed, 35551 insertions, 0 deletions
diff --git a/sourcemod-1.5-dev/GPLv2.txt b/sourcemod-1.5-dev/GPLv2.txt
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/sourcemod-1.5-dev/GPLv2.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/sourcemod-1.5-dev/GPLv3.txt b/sourcemod-1.5-dev/GPLv3.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/sourcemod-1.5-dev/GPLv3.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/sourcemod-1.5-dev/LICENSE.txt b/sourcemod-1.5-dev/LICENSE.txt
new file mode 100644
index 0000000..b8bb266
--- /dev/null
+++ b/sourcemod-1.5-dev/LICENSE.txt
@@ -0,0 +1,39 @@
+SOURCEMOD LICENSE INFORMATION
+VERSION: JUNE-13-2008
+-----------------------------
+
+SourceMod is licensed under the GNU General Public License, version 3.
+
+As a special exception, AlliedModders LLC gives you permission to link the code
+of this program (as well as its derivative works) to "Half-Life 2," the "Source
+Engine," the "SourcePawn JIT," and any Game MODs that run on software by the
+Valve Corporation. You must obey the GNU General Public License in all
+respects for all other code used. Additionally, AlliedModders LLC grants this
+exception to all derivative works.
+
+As an additional special exception to the GNU General Public License 3.0,
+AlliedModders LLC permits dual-licensing of DERIVATIVE WORKS ONLY (that is,
+SourcePawn/SourceMod Plugins and SourceMod Extensions, or any software built
+from the SourceMod SDK or header files) under the GNU General Public License
+version 2 "or any higher version." As such, you may choose for your derivative
+work(s) to be compatible with the GNU General Public License version 2 as long
+as it is also compatible with the GNU General Public License version 3, via the
+"or any higher version" clause. This is intended for compatibility with other
+software.
+
+As a final exception to the above, any derivative works created prior to this
+date (July 31, 2007) may be exclusively licensed under the GNU General Public
+License version 2 (without an "or any higher version" clause) if and only if
+the work was already GNU General Public License 2.0 exclusive. This clause is
+provided for backwards compatibility only.
+
+A copy of the JIT License is available in JIT.txt.
+A copy of the GNU General Public License 2.0 is available in GPLv2.txt.
+A copy of the GNU General Public License 3.0 is available in GPLv3.txt.
+
+SourcePawn is Copyright (C) 2006-2008 AlliedModders LLC. All rights reserved.
+SourceMod is Copyright (C) 2006-2008 AlliedModders LLC. All rights reserved.
+Pawn and SMALL are Copyright (C) 1997-2008 ITB CompuPhase.
+Source is Copyright (C) Valve Corporation.
+All trademarks are property of their respective owners in the US and other
+
diff --git a/sourcemod-1.5-dev/scripting/compile.exe b/sourcemod-1.5-dev/scripting/compile.exe
new file mode 100644
index 0000000..5cfa717
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/compile.exe
Binary files differ
diff --git a/sourcemod-1.5-dev/scripting/include/admin.inc b/sourcemod-1.5-dev/scripting/include/admin.inc
new file mode 100644
index 0000000..40c5907
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/admin.inc
@@ -0,0 +1,631 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _admin_included
+ #endinput
+#endif
+#define _admin_included
+
+/**
+ * Access levels (flags) for admins.
+ */
+enum AdminFlag
+{
+ Admin_Reservation = 0, /**< Reserved slot */
+ Admin_Generic, /**< Generic admin abilities */
+ Admin_Kick, /**< Kick another user */
+ Admin_Ban, /**< Ban another user */
+ Admin_Unban, /**< Unban another user */
+ Admin_Slay, /**< Slay/kill/damage another user */
+ Admin_Changemap, /**< Change the map */
+ Admin_Convars, /**< Change basic convars */
+ Admin_Config, /**< Change configuration */
+ Admin_Chat, /**< Special chat privileges */
+ Admin_Vote, /**< Special vote privileges */
+ Admin_Password, /**< Set a server password */
+ Admin_RCON, /**< Use RCON */
+ Admin_Cheats, /**< Change sv_cheats and use its commands */
+ Admin_Root, /**< All access by default */
+ Admin_Custom1, /**< First custom flag type */
+ Admin_Custom2, /**< Second custom flag type */
+ Admin_Custom3, /**< Third custom flag type */
+ Admin_Custom4, /**< Fourth custom flag type */
+ Admin_Custom5, /**< Fifth custom flag type */
+ Admin_Custom6, /**< Sixth custom flag type */
+ /* --- */
+};
+
+#define AdminFlags_TOTAL 21 /**< Total number of admin flags */
+
+/**
+ * @section Bitwise values definitions for admin flags.
+ */
+#define ADMFLAG_RESERVATION (1<<0) /**< Convenience macro for Admin_Reservation as a FlagBit */
+#define ADMFLAG_GENERIC (1<<1) /**< Convenience macro for Admin_Generic as a FlagBit */
+#define ADMFLAG_KICK (1<<2) /**< Convenience macro for Admin_Kick as a FlagBit */
+#define ADMFLAG_BAN (1<<3) /**< Convenience macro for Admin_Ban as a FlagBit */
+#define ADMFLAG_UNBAN (1<<4) /**< Convenience macro for Admin_Unban as a FlagBit */
+#define ADMFLAG_SLAY (1<<5) /**< Convenience macro for Admin_Slay as a FlagBit */
+#define ADMFLAG_CHANGEMAP (1<<6) /**< Convenience macro for Admin_Changemap as a FlagBit */
+#define ADMFLAG_CONVARS (1<<7) /**< Convenience macro for Admin_Convars as a FlagBit */
+#define ADMFLAG_CONFIG (1<<8) /**< Convenience macro for Admin_Config as a FlagBit */
+#define ADMFLAG_CHAT (1<<9) /**< Convenience macro for Admin_Chat as a FlagBit */
+#define ADMFLAG_VOTE (1<<10) /**< Convenience macro for Admin_Vote as a FlagBit */
+#define ADMFLAG_PASSWORD (1<<11) /**< Convenience macro for Admin_Password as a FlagBit */
+#define ADMFLAG_RCON (1<<12) /**< Convenience macro for Admin_RCON as a FlagBit */
+#define ADMFLAG_CHEATS (1<<13) /**< Convenience macro for Admin_Cheats as a FlagBit */
+#define ADMFLAG_ROOT (1<<14) /**< Convenience macro for Admin_Root as a FlagBit */
+#define ADMFLAG_CUSTOM1 (1<<15) /**< Convenience macro for Admin_Custom1 as a FlagBit */
+#define ADMFLAG_CUSTOM2 (1<<16) /**< Convenience macro for Admin_Custom2 as a FlagBit */
+#define ADMFLAG_CUSTOM3 (1<<17) /**< Convenience macro for Admin_Custom3 as a FlagBit */
+#define ADMFLAG_CUSTOM4 (1<<18) /**< Convenience macro for Admin_Custom4 as a FlagBit */
+#define ADMFLAG_CUSTOM5 (1<<19) /**< Convenience macro for Admin_Custom5 as a FlagBit */
+#define ADMFLAG_CUSTOM6 (1<<20) /**< Convenience macro for Admin_Custom6 as a FlagBit */
+
+/**
+ * @endsection
+ */
+
+/**
+ * @section Hardcoded authentication methods
+ */
+#define AUTHMETHOD_STEAM "steam" /**< SteamID based authentication */
+#define AUTHMETHOD_IP "ip" /**< IP based authentication */
+#define AUTHMETHOD_NAME "name" /**< Name based authentication */
+
+/**
+ * @endsection
+ */
+
+/**
+ * Access override types.
+ */
+enum OverrideType
+{
+ Override_Command = 1, /**< Command */
+ Override_CommandGroup, /**< Command group */
+};
+
+/**
+ * Access override rules.
+ */
+enum OverrideRule
+{
+ Command_Deny = 0,
+ Command_Allow = 1,
+};
+
+/**
+ * DEPRECATED, do not use.
+ */
+enum ImmunityType
+{
+ Immunity_Default = 1, /**< Deprecated. */
+ Immunity_Global, /**< Deprecated. */
+};
+
+/**
+ * Identifies a unique entry in the group permissions cache. These are not Handles.
+ */
+enum GroupId
+{
+ INVALID_GROUP_ID = -1, /**< An invalid/non-existent group */
+};
+
+/**
+ * Identifies a unique entry in the admin permissions cache. These are not Handles.
+ */
+enum AdminId
+{
+ INVALID_ADMIN_ID = -1, /**< An invalid/non-existent admin */
+};
+
+/**
+ * Methods of computing access permissions.
+ */
+enum AdmAccessMode
+{
+ Access_Real, /**< Access the user has inherently */
+ Access_Effective, /**< Access the user has from their groups */
+};
+
+/**
+ * Represents the various cache regions.
+ */
+enum AdminCachePart
+{
+ AdminCache_Overrides = 0, /**< Global overrides */
+ AdminCache_Groups = 1, /**< All groups (automatically invalidates admins too) */
+ AdminCache_Admins = 2, /**< All admins */
+};
+
+/**
+ * Called when part of the cache needs to be rebuilt.
+ *
+ * @param part Part of the admin cache to rebuild.
+ */
+forward OnRebuildAdminCache(AdminCachePart:part);
+
+/**
+ * Tells the admin system to dump a portion of the cache.
+ *
+ * @param part Part of the cache to dump. Specifying groups also dumps admins.
+ * @param rebuild If true, the rebuild forwards will fire.
+ * @noreturn
+ */
+native DumpAdminCache(AdminCachePart:part, bool:rebuild);
+
+/**
+ * Adds a global command flag override. Any command registered with this name
+ * will assume the new flag. This is applied retroactively as well.
+ *
+ * @param cmd String containing command name (case sensitive).
+ * @param type Override type (specific command or group).
+ * @param flags New admin flag.
+ * @noreturn
+ */
+native AddCommandOverride(const String:cmd[], OverrideType:type, flags);
+
+/**
+ * Returns a command override.
+ *
+ * @param cmd String containing command name (case sensitive).
+ * @param type Override type (specific command or group).
+ * @param flags By-reference cell to store the flag (undefined if not found).
+ * @return True if there is an override, false otherwise.
+ */
+native bool:GetCommandOverride(const String:cmd[], OverrideType:type, &flags);
+
+/**
+ * Unsets a command override.
+ *
+ * @param cmd String containing command name (case sensitive).
+ * @param type Override type (specific command or group).
+ * @noreturn
+ */
+native UnsetCommandOverride(const String:cmd[], OverrideType:type);
+
+/**
+ * Adds a new group. Name must be unique.
+ *
+ * @param group_name String containing the group name.
+ * @return A new group id, INVALID_GROUP_ID if it already exists.
+ */
+native GroupId:CreateAdmGroup(const String:group_name[]);
+
+/**
+ * Finds a group by name.
+ *
+ * @param group_name String containing the group name.
+ * @return A group id, or INVALID_GROUP_ID if not found.
+ */
+native GroupId:FindAdmGroup(const String:group_name[]);
+
+/**
+ * Adds or removes a flag from a group's flag set.
+ * @note These are called "add flags" because they add to a user's flags.
+ *
+ * @param id Group id.
+ * @param flag Admin flag to toggle.
+ * @param enabled True to set the flag, false to unset/disable.
+ * @noreturn
+ */
+native SetAdmGroupAddFlag(GroupId:id, AdminFlag:flag, bool:enabled);
+
+/**
+ * Gets the set value of an add flag on a group's flag set.
+ * @note These are called "add flags" because they add to a user's flags.
+ *
+ * @param id Group id.
+ * @param flag Admin flag to retrieve.
+ * @return True if enabled, false otherwise,
+ */
+native bool:GetAdmGroupAddFlag(GroupId:id, AdminFlag:flag);
+
+/**
+ * Returns the flag set that is added to a user from their group.
+ * @note These are called "add flags" because they add to a user's flags.
+ *
+ * @param id GroupId of the group.
+ * @return Bitstring containing the flags enabled.
+ */
+native GetAdmGroupAddFlags(GroupId:id);
+
+/**
+ * @deprecated Functionality removed.
+ */
+#pragma deprecated Use SetAdmGroupImmunityLevel() instead.
+native SetAdmGroupImmunity(GroupId:id, ImmunityType:type, bool:enabled);
+
+/**
+ * @deprecated Functionality removed.
+ */
+#pragma deprecated Use GetAdmGroupImmunityLevel() instead.
+native bool:GetAdmGroupImmunity(GroupId:id, ImmunityType:type);
+
+/**
+ * Adds immunity to a specific group.
+ *
+ * @param id Group id.
+ * @param other_id Group id to receive immunity to.
+ * @noreturn
+ */
+native SetAdmGroupImmuneFrom(GroupId:id, GroupId:other_id);
+
+/**
+ * Returns the number of specific group immunities.
+ *
+ * @param id Group id.
+ * @return Number of group immunities.
+ */
+native GetAdmGroupImmuneCount(GroupId:id);
+
+/**
+ * Returns a group that this group is immune to given an index.
+ *
+ * @param id Group id.
+ * @param number Index from 0 to N-1, from GetAdmGroupImmuneCount().
+ * @return GroupId that this group is immune to, or INVALID_GROUP_ID on failure.
+ */
+native GroupId:GetAdmGroupImmuneFrom(GroupId:id, number);
+
+/**
+ * Adds a group-specific override type.
+ *
+ * @param id Group id.
+ * @param name String containing command name (case sensitive).
+ * @param type Override type (specific command or group).
+ * @param rule Override allow/deny setting.
+ * @noreturn
+ */
+native AddAdmGroupCmdOverride(GroupId:id, const String:name[], OverrideType:type, OverrideRule:rule);
+
+/**
+ * Retrieves a group-specific command override.
+ *
+ * @param id Group id.
+ * @param name String containing command name (case sensitive).
+ * @param type Override type (specific command or group).
+ * @param rule Optional pointer to store allow/deny setting.
+ * @return True if an override exists, false otherwise.
+ */
+native bool:GetAdmGroupCmdOverride(GroupId:id, const String:name[], OverrideType:type, &OverrideRule:rule);
+
+/**
+ * Registers an authentication identity type. You normally never need to call this except for
+ * very specific systems.
+ *
+ * @param name Codename to use for your authentication type.
+ * @noreturn
+ */
+native RegisterAuthIdentType(const String:name[]);
+
+/**
+ * Creates a new admin entry in the permissions cache.
+ *
+ * @param name Name for this entry (does not have to be unique).
+ * Specify an empty string for an anonymous admin.
+ */
+native AdminId:CreateAdmin(const String:name[]="");
+
+/**
+ * Retrieves an admin's user name as made with CreateAdmin().
+ *
+ * @note This function can return UTF-8 strings, and will safely chop UTF-8 strings.
+ *
+ * @param id AdminId of the admin.
+ * @param name String buffer to store name.
+ * @param maxlength Maximum size of string buffer.
+ * @return Number of bytes written.
+ */
+native GetAdminUsername(AdminId:id, String:name[], maxlength);
+
+/**
+ * Binds an admin to an identity for fast lookup later on. The bind must be unique.
+ *
+ * @param id AdminId of the admin.
+ * @param auth Auth method to use, predefined or from RegisterAuthIdentType().
+ * @param ident String containing the arbitrary, unique identity.
+ * @return True on success, false if the auth method was not found,
+ * or ident was already taken.
+ */
+native bool:BindAdminIdentity(AdminId:id, const String:auth[], const String:ident[]);
+
+/**
+ * Sets whether or not a flag is enabled on an admin.
+ *
+ * @param id AdminId index of the admin.
+ * @param flag Admin flag to use.
+ * @param enabled True to enable, false to disable.
+ * @noreturn
+ */
+native SetAdminFlag(AdminId:id, AdminFlag:flag, bool:enabled);
+
+/**
+ * Returns whether or not a flag is enabled on an admin.
+ *
+ * @param id AdminId index of the admin.
+ * @param flag Admin flag to use.
+ * @param mode Access mode to check.
+ * @return True if enabled, false otherwise.
+ */
+native bool:GetAdminFlag(AdminId:id, AdminFlag:flag, AdmAccessMode:mode=Access_Effective);
+
+/**
+ * Returns the bitstring of access flags on an admin.
+ *
+ * @param id AdminId index of the admin.
+ * @param mode Access mode to use.
+ * @return A bitstring containing which flags are enabled.
+ */
+native GetAdminFlags(AdminId:id, AdmAccessMode:mode);
+
+/**
+ * Adds a group to an admin's inherited group list. Any flags the group has
+ * will be added to the admin's effective flags.
+ *
+ * @param id AdminId index of the admin.
+ * @param gid GroupId index of the group.
+ * @return True on success, false on invalid input or duplicate membership.
+ */
+native bool:AdminInheritGroup(AdminId:id, GroupId:gid);
+
+/**
+ * Returns the number of groups this admin is a member of.
+ *
+ * @param id AdminId index of the admin.
+ * @return Number of groups this admin is a member of.
+ */
+native GetAdminGroupCount(AdminId:id);
+
+/**
+ * Returns group information from an admin.
+ *
+ * @param id AdminId index of the admin.
+ * @param index Group number to retrieve, from 0 to N-1, where N
+ * is the value of GetAdminGroupCount(id).
+ * @param name Buffer to store the group's name.
+ * Note: This will safely chop UTF-8 strings.
+ * @param maxlength Maximum size of the output name buffer.
+ * @return A GroupId index and a name pointer, or
+ * INVALID_GROUP_ID and NULL if an error occurred.
+*/
+native GroupId:GetAdminGroup(AdminId:id, index, const String:name[], maxlength);
+
+/**
+ * Sets a password on an admin.
+ *
+ * @param id AdminId index of the admin.
+ * @param password String containing the password.
+ * @noreturn
+ */
+native SetAdminPassword(AdminId:id, const String:password[]);
+
+/**
+ * Gets an admin's password.
+ *
+ * @param id AdminId index of the admin.
+ * @param buffer Optional buffer to store the admin's password.
+ * @param maxlength Maximum size of the output name buffer.
+ * Note: This will safely chop UTF-8 strings.
+ * @return True if there was a password set, false otherwise.
+ */
+native bool:GetAdminPassword(AdminId:id, String:buffer[]="", maxlength=0);
+
+/**
+ * Attempts to find an admin by an auth method and an identity.
+ *
+ * @param auth Auth method to try.
+ * @param identity Identity string to look up.
+ * @return An AdminId index if found, INVALID_ADMIN_ID otherwise.
+ */
+native AdminId:FindAdminByIdentity(const String:auth[], const String:identity[]);
+
+/**
+ * Removes an admin entry from the cache.
+ *
+ * @note This will remove any bindings to a specific user.
+ *
+ * @param id AdminId index to remove/invalidate.
+ * @return True on success, false otherwise.
+ */
+native bool:RemoveAdmin(AdminId:id);
+
+/**
+ * Converts a flag bit string to a bit array.
+ *
+ * @param bits Bit string containing the flags.
+ * @param array Array to write the flags to. Enabled flags will be 'true'.
+ * @param maxSize Maximum number of flags the array can store.
+ * @return Number of flags written.
+ */
+native FlagBitsToBitArray(bits, bool:array[], maxSize);
+
+/**
+ * Converts a flag array to a bit string.
+ *
+ * @param array Array containing true or false for each AdminFlag.
+ * @param maxSize Maximum size of the flag array.
+ * @return A bit string composed of the array bits.
+ */
+native FlagBitArrayToBits(const bool:array[], maxSize);
+
+/**
+ * Converts an array of flags to bits.
+ *
+ * @param array Array containing flags that are enabled.
+ * @param numFlags Number of flags in the array.
+ * @return A bit string composed of the array flags.
+ */
+native FlagArrayToBits(const AdminFlag:array[], numFlags);
+
+/**
+ * Converts a bit string to an array of flags.
+ *
+ * @param bits Bit string containing the flags.
+ * @param array Output array to write flags.
+ * @param maxSize Maximum size of the flag array.
+ * @return Number of flags written.
+ */
+native FlagBitsToArray(bits, AdminFlag:array[], maxSize);
+
+/**
+ * Finds a flag by its string name.
+ *
+ * @param name Flag name (like "kick"), case sensitive.
+ * @param flag Variable to store flag in.
+ * @return True on success, false if not found.
+ */
+native bool:FindFlagByName(const String:name[], &AdminFlag:flag);
+
+/**
+ * Finds a flag by a given character.
+ *
+ * @param c Flag ASCII character/token.
+ * @param flag Variable to store flag in.
+ * @return True on success, false if not found.
+ */
+native bool:FindFlagByChar(c, &AdminFlag:flag);
+
+/**
+ * Finds a flag char by a gived admin flag.
+ *
+ * @param flag Flag to look up.
+ * @param c Variable to store flag char.
+ * @return True on success, false if not found.
+ */
+native bool:FindFlagChar(AdminFlag:flag, &c);
+
+/**
+ * Converts a string of flag characters to a bit string.
+ *
+ * @param flags Flag ASCII string.
+ * @param numchars Optional variable to store the number of bytes read.
+ * @return Bit string of ADMFLAG values.
+ */
+native ReadFlagString(const String:flags[], &numchars=0);
+
+/**
+ * Tests whether one admin can target another.
+ *
+ * The heuristics for this check are as follows:
+ * 0. If the targeting AdminId is INVALID_ADMIN_ID, targeting fails.
+ * 1. If the targeted AdminId is INVALID_ADMIN_ID, targeting succeeds.
+ * 2. If the targeted AdminId is the same as the targeting AdminId,
+ * (self) targeting succeeds.
+ * 3. If the targeting admin is root, targeting succeeds.
+ * 4. If the targeted admin has access higher (as interpreted by
+ * (sm_immunity_mode) than the targeting admin, then targeting fails.
+ * 5. If the targeted admin has specific immunity from the
+ * targeting admin via group immunities, targeting fails.
+ * 6. Targeting succeeds.
+ *
+ * @param admin Admin doing the targetting (may be INVALID_ADMIN_ID).
+ * @param target Target admin (may be INVALID_ADMIN_ID).
+ * @return True if targetable, false if immune.
+ */
+native CanAdminTarget(AdminId:admin, AdminId:target);
+
+/**
+ * Creates an admin auth method. This does not need to be called more than once
+ * per method, ever.
+ *
+ * @param method Name of the authentication method.
+ * @return True on success, false on failure.
+ */
+native bool:CreateAuthMethod(const String:method[]);
+
+/**
+ * Sets a group's immunity level.
+ *
+ * @param gid Group Id.
+ * @param level Immunity level value.
+ * @return Old immunity level value.
+ */
+native SetAdmGroupImmunityLevel(GroupId:gid, level);
+
+/**
+ * Gets a group's immunity level (defaults to 0).
+ *
+ * @param gid Group Id.
+ * @return Immunity level value.
+ */
+native GetAdmGroupImmunityLevel(GroupId:gid);
+
+/**
+ * Sets an admin's immunity level.
+ *
+ * @param id Admin Id.
+ * @param level Immunity level value.
+ * @return Old immunity level value.
+ */
+native SetAdminImmunityLevel(AdminId:id, level);
+
+/**
+ * Gets an admin's immunity level.
+ *
+ * @param id Admin Id.
+ * @return Immunity level value.
+ */
+native GetAdminImmunityLevel(AdminId:id);
+
+/**
+ * Converts a flag to its single bit.
+ *
+ * @param flag Flag to convert.
+ * @return Bit representation of the flag.
+ */
+stock FlagToBit(AdminFlag:flag)
+{
+ return (1<<_:flag);
+}
+
+/**
+ * Converts a bit to an AdminFlag.
+ *
+ * @param bit Bit to convert.
+ * @param flag Stores the converted flag by reference.
+ * @return True on success, false otherwise.
+ */
+stock bool:BitToFlag(bit, &AdminFlag:flag)
+{
+ new AdminFlag:array[1];
+
+ if (FlagBitsToArray(bit, array, 1))
+ {
+ flag = array[0];
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/sourcemod-1.5-dev/scripting/include/adminmenu.inc b/sourcemod-1.5-dev/scripting/include/adminmenu.inc
new file mode 100644
index 0000000..f96eb2a
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/adminmenu.inc
@@ -0,0 +1,154 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _adminmenu_included
+ #endinput
+#endif
+#define _adminmenu_included
+
+/* Decide whether topmenus should be required */
+#if !defined REQUIRE_PLUGIN
+ #if defined REQUIRE_EXTENSIONS
+ #define TEMP_REQUIRE_EXTENSIONS
+ #undef REQUIRE_EXTENSIONS
+ #endif
+#endif
+
+#include <topmenus>
+
+/* Restore old REQUIRE_EXTENSIONS value if necessary */
+#if defined TEMP_REQUIRE_EXTENSIONS
+ #define REQUIRE_EXTENSIONS
+ #undef TEMP_REQUIRE_EXTENSIONS
+#endif
+
+/** Category for player commands. */
+#define ADMINMENU_PLAYERCOMMANDS "PlayerCommands"
+/** Category for server commands. */
+#define ADMINMENU_SERVERCOMMANDS "ServerCommands"
+/** Category for voting commands. */
+#define ADMINMENU_VOTINGCOMMANDS "VotingCommands"
+
+/**
+ * Called when the admin menu is created and 3rd party plugins can grab
+ * the Handle or add categories.
+ *
+ * @param topmenu Handle to the admin menu's TopMenu.
+ * @noreturn
+ */
+forward OnAdminMenuCreated(Handle:topmenu);
+
+/**
+ * Called when the admin menu is ready to have items added.
+ *
+ * @param topmenu Handle to the admin menu's TopMenu.
+ * @noreturn
+ */
+forward OnAdminMenuReady(Handle:topmenu);
+
+/**
+ * Retrieves the Handle to the admin top menu.
+ *
+ * @return Handle to the admin menu's TopMenu,
+ * or INVALID_HANDLE if not created yet.
+ */
+native Handle:GetAdminTopMenu();
+
+/**
+ * Adds targets to an admin menu.
+ *
+ * Each client is displayed as: name (userid)
+ * Each item contains the userid as a string for its info.
+ *
+ * @param menu Menu Handle.
+ * @param source_client Source client, or 0 to ignore immunity.
+ * @param in_game_only True to only select in-game players.
+ * @param alive_only True to only select alive players.
+ * @return Number of clients added.
+ */
+native AddTargetsToMenu(Handle:menu,
+ source_client,
+ bool:in_game_only=true,
+ bool:alive_only=false);
+
+/**
+ * Adds targets to an admin menu.
+ *
+ * Each client is displayed as: name (userid)
+ * Each item contains the userid as a string for its info.
+ *
+ * @param menu Menu Handle.
+ * @param source_client Source client, or 0 to ignore immunity.
+ * @param flags COMMAND_FILTER flags from commandfilters.inc.
+ * @return Number of clients added.
+ */
+native AddTargetsToMenu2(Handle:menu, source_client, flags);
+
+/**
+ * Re-displays the admin menu to a client after selecting an item.
+ * Auto-aborts if the Handle is invalid.
+ *
+ * @param topmenu TopMenu Handle.
+ * @param client Client index.
+ * @return True on success, false on failure.
+ */
+stock bool:RedisplayAdminMenu(Handle:topmenu, client)
+{
+ if (topmenu == INVALID_HANDLE)
+ {
+ return false;
+ }
+
+ return DisplayTopMenu(topmenu, client, TopMenuPosition_LastCategory);
+}
+
+/* DO NOT EDIT BELOW THIS LINE */
+
+public SharedPlugin:__pl_adminmenu =
+{
+ name = "adminmenu",
+ file = "adminmenu.smx",
+#if defined REQUIRE_PLUGIN
+ required = 1,
+#else
+ required = 0,
+#endif
+};
+
+#if !defined REQUIRE_PLUGIN
+public __pl_adminmenu_SetNTVOptional()
+{
+ MarkNativeAsOptional("GetAdminTopMenu");
+ MarkNativeAsOptional("AddTargetsToMenu");
+ MarkNativeAsOptional("AddTargetsToMenu2");
+}
+#endif
diff --git a/sourcemod-1.5-dev/scripting/include/adt.inc b/sourcemod-1.5-dev/scripting/include/adt.inc
new file mode 100644
index 0000000..75051bf
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/adt.inc
@@ -0,0 +1,40 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _adt_included
+ #endinput
+#endif
+#define _adt_included
+
+#include <adt_array>
+#include <adt_trie>
+#include <adt_stack>
diff --git a/sourcemod-1.5-dev/scripting/include/adt_array.inc b/sourcemod-1.5-dev/scripting/include/adt_array.inc
new file mode 100644
index 0000000..798ae55
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/adt_array.inc
@@ -0,0 +1,283 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _adt_array_included
+ #endinput
+#endif
+#define _adt_array_included
+
+/**
+ * Given a maximum string size (including the null terminator),
+ * returns the number of cells required to fit that string.
+ *
+ * @param size Number of bytes.
+ * @return Minimum number of cells required to fit the byte count.
+ */
+stock ByteCountToCells(size)
+{
+ if (!size)
+ {
+ return 1;
+ }
+
+ return (size + 3) / 4;
+}
+
+/**
+ * Creates a dynamic global cell array. While slower than a normal array,
+ * it can be used globally AND dynamically, which is otherwise impossible.
+ *
+ * The contents of the array are uniform; i.e. storing a string at index X
+ * and then retrieving it as an integer is NOT the same as StringToInt()!
+ * The "blocksize" determines how many cells each array slot has; it cannot
+ * be changed after creation.
+ *
+ * @param blocksize The number of cells each member of the array can
+ * hold. For example, 32 cells is equivalent to:
+ * new Array[X][32]
+ * @param startsize Initial size of the array. Note that data will
+ * NOT be auto-intialized.
+ * @return New Handle to the array object.
+ */
+native Handle:CreateArray(blocksize=1, startsize=0);
+
+/**
+ * Clears an array of all entries. This is the same as ResizeArray(0).
+ *
+ * @param array Array Handle.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native ClearArray(Handle:array);
+
+/**
+ * Clones an array, returning a new handle with the same size and data. This should NOT
+ * be confused with CloneHandle. This is a completely new handle with the same data but
+ * no relation to the original. You MUST close it.
+ *
+ * @param array Array handle to be cloned
+ * @return New handle to the cloned array object
+ * @error Invalid Handle
+ */
+native Handle:CloneArray(Handle:array);
+
+/**
+ * Resizes an array. If the size is smaller than the current size,
+ * the array is truncated.
+ *
+ * @param array Array Handle.
+ * @param newsize New size.
+ * @noreturn
+ * @error Invalid Handle or out of memory.
+ */
+native bool:ResizeArray(Handle:array, newsize);
+
+/**
+ * Returns the array size.
+ *
+ * @param array Array Handle.
+ * @return Number of elements in the array.
+ * @error Invalid Handle.
+ */
+native GetArraySize(Handle:array);
+
+/**
+ * Pushes a value onto the end of an array, adding a new index.
+ *
+ * This may safely be used even if the array has a blocksize
+ * greater than 1.
+ *
+ * @param array Array Handle.
+ * @param value Value to push.
+ * @return Index of the new entry.
+ * @error Invalid Handle or out of memory.
+ */
+native PushArrayCell(Handle:array, any:value);
+
+/**
+ * Pushes a string onto the end of an array, truncating it
+ * if it is too big.
+ *
+ * @param array Array Handle.
+ * @param value String to push.
+ * @return Index of the new entry.
+ * @error Invalid Handle or out of memory.
+ */
+native PushArrayString(Handle:array, const String:value[]);
+
+/**
+ * Pushes an array of cells onto the end of an array. The cells
+ * are pushed as a block (i.e. the entire array sits at the index),
+ * rather than pushing each cell individually.
+ *
+ * @param array Array Handle.
+ * @param values Block of values to copy.
+ * @param size If not set, the number of elements copied from the array
+ * will be equal to the blocksize. If set higher than the
+ * blocksize, the operation will be truncated.
+ * @return Index of the new entry.
+ * @error Invalid Handle or out of memory.
+ */
+native PushArrayArray(Handle:array, const any:values[], size=-1);
+
+/**
+ * Retrieves a cell value from an array.
+ *
+ * @param array Array Handle.
+ * @param index Index in the array.
+ * @param block Optionally specify which block to read from
+ * (useful if the blocksize > 0).
+ * @param asChar Optionally read as a byte instead of a cell.
+ * @return Value read.
+ * @error Invalid Handle, invalid index, or invalid block.
+ */
+native any:GetArrayCell(Handle:array, index, block=0, bool:asChar=false);
+
+/**
+ * Retrieves a string value from an array.
+ *
+ * @param array Array Handle.
+ * @param index Index in the array.
+ * @param buffer Buffer to copy to.
+ * @param maxlength Maximum size of the buffer.
+ * @return Number of characters copied.
+ * @error Invalid Handle or invalid index.
+ */
+native GetArrayString(Handle:array, index, String:buffer[], maxlength);
+
+/**
+ * Retrieves an array of cells from an array.
+ *
+ * @param array Array Handle.
+ * @param index Index in the array.
+ * @param buffer Buffer to store the array in.
+ * @param size If not set, assumes the buffer size is equal to the
+ * blocksize. Otherwise, the size passed is used.
+ * @return Number of cells copied.
+ * @error Invalid Handle or invalid index.
+ */
+native GetArrayArray(Handle:array, index, any:buffer[], size=-1);
+
+/**
+ * Sets a cell value in an array.
+ *
+ * @param array Array Handle.
+ * @param index Index in the array.
+ * @param value Cell value to set.
+ * @param block Optionally specify which block to write to
+ * (useful if the blocksize > 0).
+ * @param asChar Optionally set as a byte instead of a cell.
+ * @noreturn
+ * @error Invalid Handle, invalid index, or invalid block.
+ */
+native SetArrayCell(Handle:array, index, any:value, block=0, bool:asChar=false);
+
+/**
+ * Sets a string value in an array.
+ *
+ * @param array Array Handle.
+ * @param index Index in the array.
+ * @param value String value to set.
+ * @return Number of characters copied.
+ * @error Invalid Handle or invalid index.
+ */
+native SetArrayString(Handle:array, index, const String:value[]);
+
+/**
+ * Sets an array of cells in an array.
+ *
+ * @param array Array Handle.
+ * @param index Index in the array.
+ * @param values Array to copy.
+ * @param size If not set, assumes the buffer size is equal to the
+ * blocksize. Otherwise, the size passed is used.
+ * @return Number of cells copied.
+ * @error Invalid Handle or invalid index.
+ */
+native SetArrayArray(Handle:array, index, const any:values[], size=-1);
+
+/**
+ * Shifts an array up. All array contents after and including the given
+ * index are shifted up by one, and the given index is then "free."
+ * After shifting, the contents of the given index is undefined.
+ *
+ * @param array Array Handle.
+ * @param index Index in the array to shift up from.
+ * @noreturn
+ * @error Invalid Handle or invalid index.
+ */
+native ShiftArrayUp(Handle:array, index);
+
+/**
+ * Removes an array index, shifting the entire array down from that position
+ * on. For example, if item 8 of 10 is removed, the last 3 items will then be
+ * (6,7,8) instead of (7,8,9), and all indexes before 8 will remain unchanged.
+ *
+ * @param array Array Handle.
+ * @param index Index in the array to remove at.
+ * @noreturn
+ * @error Invalid Handle or invalid index.
+ */
+native RemoveFromArray(Handle:array, index);
+
+/**
+ * Swaps two items in the array.
+ *
+ * @param array Array Handle.
+ * @param index1 First index.
+ * @param index2 Second index.
+ * @noreturn
+ * @error Invalid Handle or invalid index.
+ */
+native SwapArrayItems(Handle:array, index1, index2);
+
+/**
+ * Returns the index for the first occurance of the provided string. If the string
+ * cannot be located, -1 will be returned.
+ *
+ * @param array Array Handle.
+ * @param item String to search for
+ * @return Array index, or -1 on failure
+ * @error Invalid Handle
+ */
+native FindStringInArray(Handle:array, const String:item[]);
+
+/**
+ * Returns the index for the first occurance of the provided value. If the value
+ * cannot be located, -1 will be returned.
+ *
+ * @param array Array Handle.
+ * @param item Value to search for
+ * @return Array index, or -1 on failure
+ * @error Invalid Handle
+ */
+native FindValueInArray(Handle:array, any:item);
diff --git a/sourcemod-1.5-dev/scripting/include/adt_stack.inc b/sourcemod-1.5-dev/scripting/include/adt_stack.inc
new file mode 100644
index 0000000..54029c3
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/adt_stack.inc
@@ -0,0 +1,154 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _adt_stack_included
+ #endinput
+#endif
+#define _adt_stack_included
+
+/**
+ * Creates a stack structure. A stack is a LIFO (last in, first out)
+ * vector (array) of items. It has O(1) insertion and O(1) removal.
+ *
+ * Stacks have two operations: Push (adding an item) and Pop (removes
+ * items in reverse-push order).
+ *
+ * The contents of the stack are uniform; i.e. storing a string and then
+ * retrieving it as an integer is NOT the same as StringToInt()!
+ *
+ * The "blocksize" determines how many cells each slot has; it cannot
+ * be changed after creation.
+ *
+ * @param blocksize The number of cells each entry in the stack can
+ * hold. For example, 32 cells is equivalent to:
+ * new Array[X][32]
+ * @return New stack Handle.
+ */
+native Handle:CreateStack(blocksize=1);
+
+/**
+ * Pushes a value onto the end of the stack, adding a new index.
+ *
+ * This may safely be used even if the stack has a blocksize
+ * greater than 1.
+ *
+ * @param stack Stack Handle.
+ * @param value Value to push.
+ * @noreturn
+ * @error Invalid Handle or out of memory.
+ */
+native PushStackCell(Handle:stack, any:value);
+
+/**
+ * Pushes a string onto the end of a stack, truncating it if it is
+ * too big.
+ *
+ * @param stack Stack Handle.
+ * @param value String to push.
+ * @noreturn
+ * @error Invalid Handle or out of memory.
+ */
+native PushStackString(Handle:stack, const String:value[]);
+
+/**
+ * Pushes an array of cells onto the end of a stack. The cells
+ * are pushed as a block (i.e. the entire array takes up one stack slot),
+ * rather than pushing each cell individually.
+ *
+ * @param stack Stack Handle.
+ * @param values Block of values to copy.
+ * @param size If not set, the number of elements copied from the array
+ * will be equal to the blocksize. If set higher than the
+ * blocksize, the operation will be truncated.
+ * @noreturn
+ * @error Invalid Handle or out of memory.
+ */
+native PushStackArray(Handle:stack, const any:values[], size=-1);
+
+/**
+ * Pops a cell value from a stack.
+ *
+ * @param stack Stack Handle.
+ * @param value Variable to store the value.
+ * @param block Optionally specify which block to read from
+ * (useful if the blocksize > 0).
+ * @param asChar Optionally read as a byte instead of a cell.
+ * @return True on success, false if the stack is empty.
+ * @error Invalid Handle.
+ */
+native bool:PopStackCell(Handle:stack, &any:value, block=0, bool:asChar=false);
+
+/**
+ * Pops a string value from a stack.
+ *
+ * @param stack Stack Handle.
+ * @param buffer Buffer to store string.
+ * @param maxlength Maximum size of the buffer.
+ * @return True on success, false if the stack is empty.
+ * @error Invalid Handle.
+ */
+native bool:PopStackString(Handle:stack, String:buffer[], maxlength, &written=0);
+
+/**
+ * Pops an array of cells from a stack.
+ *
+ * @param stack Stack Handle.
+ * @param buffer Buffer to store the array in.
+ * @param size If not set, assumes the buffer size is equal to the
+ * blocksize. Otherwise, the size passed is used.
+ * @return True on success, false if the stack is empty.
+ * @error Invalid Handle.
+ */
+native bool:PopStackArray(Handle:stack, any:buffer[], size=-1);
+
+/**
+ * Checks if a stack is empty.
+ *
+ * @param stack Stack Handle.
+ * @return True if empty, false if not empty.
+ * @error Invalid Handle.
+ */
+native bool:IsStackEmpty(Handle:stack);
+
+/**
+ * Pops a value off a stack, ignoring it completely.
+ *
+ * @param stack Stack Handle.
+ * @return True if something was popped, false otherwise.
+ * @error Invalid Handle.
+ */
+stock PopStack(Handle:stack)
+{
+ new value;
+
+ return PopStackCell(stack, value);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/adt_trie.inc b/sourcemod-1.5-dev/scripting/include/adt_trie.inc
new file mode 100644
index 0000000..4e9f120
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/adt_trie.inc
@@ -0,0 +1,156 @@
+/**
+ * vim: set ts=4 sw=4 tw=99 noet :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _adt_trie_included
+ #endinput
+#endif
+#define _adt_trie_included
+
+/**
+ * Creates a hash map. A hash map is a container that can map strings (called
+ * "keys") to arbitrary values (cells, arrays, or strings). Keys in a hash map
+ * are unique. That is, there is at most one entry in the map for a given key.
+ *
+ * Insertion, deletion, and lookup in a hash map are all considered to be fast
+ * operations, amortized to O(1), or constant time.
+ *
+ * The word "Trie" in this API is historical. As of SourceMod 1.6, tries have
+ * been internally replaced with hash tables, which have O(1) insertion time
+ * instead of O(n).
+ *
+ * @return New Map Handle, which must be freed via CloseHandle().
+ */
+native Handle:CreateTrie();
+
+/**
+ * Sets a value in a hash map, either inserting a new entry or replacing an old one.
+ *
+ * @param map Map Handle.
+ * @param key Key string.
+ * @param value Value to store at this key.
+ * @param replace If false, operation will fail if the key is already set.
+ * @return True on success, false on failure.
+ * @error Invalid Handle.
+ */
+native bool:SetTrieValue(Handle:map, const String:key[], any:value, bool:replace=true);
+
+/**
+ * Sets an array value in a Map, either inserting a new entry or replacing an old one.
+ *
+ * @param map Map Handle.
+ * @param key Key string.
+ * @param array Array to store.
+ * @param num_items Number of items in the array.
+ * @param replace If false, operation will fail if the key is already set.
+ * @return True on success, false on failure.
+ * @error Invalid Handle.
+ */
+native bool:SetTrieArray(Handle:map, const String:key[], const any:array[], num_items, bool:replace=true);
+
+/**
+ * Sets a string value in a Map, either inserting a new entry or replacing an old one.
+ *
+ * @param map Map Handle.
+ * @param key Key string.
+ * @param value String to store.
+ * @param replace If false, operation will fail if the key is already set.
+ * @return True on success, false on failure.
+ * @error Invalid Handle.
+ */
+native bool:SetTrieString(Handle:map, const String:key[], const String:value[], bool:replace=true);
+
+/**
+ * Retrieves a value in a Map.
+ *
+ * @param map Map Handle.
+ * @param key Key string.
+ * @param value Variable to store value.
+ * @return True on success. False if the key is not set, or the key is set
+ * as an array or string (not a value).
+ * @error Invalid Handle.
+ */
+native bool:GetTrieValue(Handle:map, const String:key[], &any:value);
+
+/**
+ * Retrieves an array in a Map.
+ *
+ * @param map Map Handle.
+ * @param key Key string.
+ * @param array Buffer to store array.
+ * @param max_size Maximum size of array buffer.
+ * @param size Optional parameter to store the number of elements written to the buffer.
+ * @return True on success. False if the key is not set, or the key is set
+ * as a value or string (not an array).
+ * @error Invalid Handle.
+ */
+native bool:GetTrieArray(Handle:map, const String:key[], any:array[], max_size, &size=0);
+
+/**
+ * Retrieves a string in a Map.
+ *
+ * @param map Map Handle.
+ * @param key Key string.
+ * @param value Buffer to store value.
+ * @param max_size Maximum size of string buffer.
+ * @param size Optional parameter to store the number of bytes written to the buffer.
+ * @return True on success. False if the key is not set, or the key is set
+ * as a value or array (not a string).
+ * @error Invalid Handle.
+ */
+native bool:GetTrieString(Handle:map, const String:key[], String:value[], max_size, &size=0);
+
+/**
+ * Removes a key entry from a Map.
+ *
+ * @param map Map Handle.
+ * @param key Key string.
+ * @return True on success, false if the value was never set.
+ * @error Invalid Handle.
+ */
+native RemoveFromTrie(Handle:map, const String:key[]);
+
+/**
+ * Clears all entries from a Map.
+ *
+ * @param map Map Handle.
+ * @error Invalid Handle.
+ */
+native ClearTrie(Handle:map);
+
+/**
+ * Retrieves the number of elements in a map.
+ *
+ * @param map Map Handle.
+ * @return Number of elements in the trie.
+ * @error Invalid Handle.
+ */
+native GetTrieSize(Handle:map);
diff --git a/sourcemod-1.5-dev/scripting/include/banning.inc b/sourcemod-1.5-dev/scripting/include/banning.inc
new file mode 100644
index 0000000..038b113
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/banning.inc
@@ -0,0 +1,157 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _banning_included
+ #endinput
+#endif
+#define _banning_included
+
+#define BANFLAG_AUTO (1<<0) /**< Auto-detects whether to ban by steamid or IP */
+#define BANFLAG_IP (1<<1) /**< Always ban by IP address */
+#define BANFLAG_AUTHID (1<<2) /**< Always ban by authstring (for BanIdentity) if possible */
+#define BANFLAG_NOKICK (1<<3) /**< Does not kick the client */
+
+/**
+ * Called for calls to BanClient() with a non-empty command.
+ *
+ * @param client Client being banned.
+ * @param time Time the client is being banned for (0 = permanent).
+ * @param flags One if AUTHID or IP will be enabled. If AUTO is also
+ * enabled, it means Core autodetected which to use.
+ * @param reason Reason passed via BanClient().
+ * @param kick_message Kick message passed via BanClient().
+ * @param command Command string to identify the ban source.
+ * @param source Source value passed via BanClient().
+ * @return Plugin_Handled to block the actual server banning.
+ * Kicking will still occur.
+ */
+forward Action:OnBanClient(client,
+ time,
+ flags,
+ const String:reason[],
+ const String:kick_message[],
+ const String:command[],
+ any:source);
+
+/**
+ * Called for calls to BanIdentity() with a non-empty command.
+ *
+ * @param identity Identity string being banned (authstring or ip).
+ * @param time Time the client is being banned for (0 = permanent).
+ * @param flags Ban flags (only IP or AUTHID are valid here).
+ * @param reason Reason passed via BanIdentity().
+ * @param command Command string to identify the ban source.
+ * @param source Source value passed via BanIdentity().
+ * @return Plugin_Handled to block the actual server banning.
+ */
+forward Action:OnBanIdentity(const String:identity[],
+ time,
+ flags,
+ const String:reason[],
+ const String:command[],
+ any:source);
+
+/**
+ * Called for calls to RemoveBan() with a non-empty command.
+ *
+ * @param identity Identity string being banned (authstring or ip).
+ * @param flags Ban flags (only IP or AUTHID are valid here).
+ * @param command Command string to identify the ban source.
+ * @param source Source value passed via BanIdentity().
+ * @return Plugin_Handled to block the actual server banning.
+ */
+forward Action:OnRemoveBan(const String:identity[],
+ flags,
+ const String:command[],
+ any:source);
+
+/**
+ * Bans a client.
+ *
+ * @param client Client being banned.
+ * @param time Time (in minutes) to ban (0 = permanent).
+ * @param flags Flags for controlling the ban mechanism. If AUTHID
+ * is set and no AUTHID is available, the ban will fail
+ * unless AUTO is also flagged.
+ * @param reason Reason to ban the client for.
+ * @param kick_message Message to display to the user when kicking.
+ * @param command Command string to identify the source. If this is left
+ * empty, then the OnBanClient forward will not be called.
+ * @param source A source value that could be interpreted as a player
+ * index of any sort (not actually checked by Core).
+ * @return True on success, false on failure.
+ * @error Invalid client index or client not in game.
+ */
+native bool:BanClient(client,
+ time,
+ flags,
+ const String:reason[],
+ const String:kick_message[]="",
+ const String:command[]="",
+ any:source=0);
+
+/**
+ * Bans an identity (either an IP address or auth string).
+ *
+ * @param identity String to ban (ip or authstring).
+ * @param time Time to ban for (0 = permanent).
+ * @param flags Flags (only IP and AUTHID are valid flags here).
+ * @param reason Ban reason string.
+ * @param command Command string to identify the source. If this is left
+ * empty, then the OnBanIdentity forward will not be called.
+ * @param source A source value that could be interpreted as a player
+ * index of any sort (not actually checked by Core).
+ * @return True on success, false on failure.
+ */
+native bool:BanIdentity(const String:identity[],
+ time,
+ flags,
+ const String:reason[],
+ const String:command[]="",
+ any:source=0);
+
+/**
+ * Removes a ban that was written to the server (either in memory or on disk).
+ *
+ * @param identity String to unban (ip or authstring).
+ * @param flags Flags (only IP and AUTHID are valid flags here).
+ * @param command Command string to identify the source. If this is left
+ * empty, then OnRemoveBan will not be called.
+ * @param source A source value that could be interpreted as a player
+ * index of any sort (not actually checked by Core).
+ * @return True on success, false on failure.
+ */
+native bool:RemoveBan(const String:identity[],
+ flags,
+ const String:command[]="",
+ any:source=0);
+
diff --git a/sourcemod-1.5-dev/scripting/include/basecomm.inc b/sourcemod-1.5-dev/scripting/include/basecomm.inc
new file mode 100644
index 0000000..832afbc
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/basecomm.inc
@@ -0,0 +1,109 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2011 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _basecomm_included
+ #endinput
+#endif
+#define _basecomm_included
+
+/**
+ * Called when a client is muted or unmuted
+ *
+ * @param client Client index
+ * @param muteState True if client was muted, false otherwise
+ */
+ forward BaseComm_OnClientMute(client, bool:muteState);
+
+ /**
+ * Called when a client is gagged or ungagged
+ *
+ * @param client Client index
+ * @param gagState True if client was gaged, false otherwise
+ */
+ forward BaseComm_OnClientGag(client, bool:gagState);
+
+/**
+ * Returns whether or not a client is gagged
+ *
+ * @param client Client index.
+ * @return True if client is gagged, false otherwise.
+ */
+native bool:BaseComm_IsClientGagged(client);
+
+/**
+ * Returns whether or not a client is muted
+ *
+ * @param client Client index.
+ * @return True if client is muted, false otherwise.
+ */
+native bool:BaseComm_IsClientMuted(client);
+
+/**
+ * Sets a client's gag state
+ *
+ * @param client Client index.
+ * @param gagState True to gag client, false to ungag.
+ * @return True if this caused a change in gag state, false otherwise.
+ */
+native bool:BaseComm_SetClientGag(client, bool:gagState);
+
+/**
+ * Sets a client's mute state
+ *
+ * @param client Client index.
+ * @param muteState True to mute client, false to unmute.
+ * @return True if this caused a change in mute state, false otherwise.
+ */
+native bool:BaseComm_SetClientMute(client, bool:muteState);
+
+/* DO NOT EDIT BELOW THIS LINE */
+
+public SharedPlugin:__pl_basecomm =
+{
+ name = "basecomm",
+ file = "basecomm.smx",
+#if defined REQUIRE_PLUGIN
+ required = 1,
+#else
+ required = 0,
+#endif
+};
+
+#if !defined REQUIRE_PLUGIN
+public __pl_basecomm_SetNTVOptional()
+{
+ MarkNativeAsOptional("BaseComm_IsClientGagged");
+ MarkNativeAsOptional("BaseComm_IsClientMuted");
+ MarkNativeAsOptional("BaseComm_SetClientGag");
+ MarkNativeAsOptional("BaseComm_SetClientMute");
+}
+#endif
diff --git a/sourcemod-1.5-dev/scripting/include/bitbuffer.inc b/sourcemod-1.5-dev/scripting/include/bitbuffer.inc
new file mode 100644
index 0000000..fd1c18e
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/bitbuffer.inc
@@ -0,0 +1,325 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _bitbuffer_included
+ #endinput
+#endif
+#define _bitbuffer_included
+
+/**
+ * Writes a single bit to a writable bitbuffer (bf_write).
+ *
+ * @param bf bf_write handle to write to.
+ * @param bit Bit to write (true for 1, false for 0).
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfWriteBool(Handle:bf, bool:bit);
+
+/**
+ * Writes a byte to a writable bitbuffer (bf_write).
+ *
+ * @param bf bf_write handle to write to.
+ * @param byte Byte to write (value will be written as 8bit).
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfWriteByte(Handle:bf, byte);
+
+/**
+ * Writes a byte to a writable bitbuffer (bf_write).
+ *
+ * @param bf bf_write handle to write to.
+ * @param chr Character to write.
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfWriteChar(Handle:bf, chr);
+
+/**
+ * Writes a 16bit integer to a writable bitbuffer (bf_write).
+ *
+ * @param bf bf_write handle to write to.
+ * @param num Integer to write (value will be written as 16bit).
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfWriteShort(Handle:bf, num);
+
+/**
+ * Writes a 16bit unsigned integer to a writable bitbuffer (bf_write).
+ *
+ * @param bf bf_write handle to write to.
+ * @param num Integer to write (value will be written as 16bit).
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfWriteWord(Handle:bf, num);
+
+/**
+ * Writes a normal integer to a writable bitbuffer (bf_write).
+ *
+ * @param bf bf_write handle to write to.
+ * @param num Integer to write (value will be written as 32bit).
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfWriteNum(Handle:bf, num);
+
+/**
+ * Writes a floating point number to a writable bitbuffer (bf_write).
+ *
+ * @param bf bf_write handle to write to.
+ * @param num Number to write.
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfWriteFloat(Handle:bf, Float:num);
+
+/**
+ * Writes a string to a writable bitbuffer (bf_write).
+ *
+ * @param bf bf_write handle to write to.
+ * @param string Text string to write.
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfWriteString(Handle:bf, const String:string[]);
+
+/**
+ * Writes an entity to a writable bitbuffer (bf_write).
+ * @note This is a wrapper around BfWriteShort().
+ *
+ * @param bf bf_write handle to write to.
+ * @param ent Entity index to write.
+ * @noreturn
+ * @error Invalid or incorrect Handle, or invalid entity.
+ */
+native BfWriteEntity(Handle:bf, ent);
+
+/**
+ * Writes a bit angle to a writable bitbuffer (bf_write).
+ *
+ * @param bf bf_write handle to write to.
+ * @param angle Angle to write.
+ * @param numBits Optional number of bits to use.
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfWriteAngle(Handle:bf, Float:angle, numBits=8);
+
+/**
+ * Writes a coordinate to a writable bitbuffer (bf_write).
+ *
+ * @param bf bf_write handle to write to.
+ * @param coord Coordinate to write.
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfWriteCoord(Handle:bf, Float:coord);
+
+/**
+ * Writes a 3D vector of coordinates to a writable bitbuffer (bf_write).
+ *
+ * @param bf bf_write handle to write to.
+ * @param coord Coordinate array to write.
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfWriteVecCoord(Handle:bf, Float:coord[3]);
+
+/**
+ * Writes a 3D normal vector to a writable bitbuffer (bf_write).
+ *
+ * @param bf bf_write handle to write to.
+ * @param vec Vector to write.
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfWriteVecNormal(Handle:bf, Float:vec[3]);
+
+/**
+ * Writes a 3D angle vector to a writable bitbuffer (bf_write).
+ *
+ * @param bf bf_write handle to write to.
+ * @param angles Angle vector to write.
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfWriteAngles(Handle:bf, Float:angles[3]);
+
+/**
+ * Reads a single bit from a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @return Bit value read.
+ * @error Invalid or incorrect Handle.
+ */
+native bool:BfReadBool(Handle:bf);
+
+/**
+ * Reads a byte from a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @return Byte value read (read as 8bit).
+ * @error Invalid or incorrect Handle.
+ */
+native BfReadByte(Handle:bf);
+
+/**
+ * Reads a character from a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @return Character value read.
+ * @error Invalid or incorrect Handle.
+ */
+native BfReadChar(Handle:bf);
+
+/**
+ * Reads a 16bit integer from a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @return Integer value read (read as 16bit).
+ * @error Invalid or incorrect Handle.
+ */
+native BfReadShort(Handle:bf);
+
+/**
+ * Reads a 16bit unsigned integer from a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @return Integer value read (read as 16bit).
+ * @error Invalid or incorrect Handle.
+ */
+native BfReadWord(Handle:bf);
+
+/**
+ * Reads a normal integer to a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @return Integer value read (read as 32bit).
+ * @error Invalid or incorrect Handle.
+ */
+native BfReadNum(Handle:bf);
+
+/**
+ * Reads a floating point number from a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @return Floating point value read.
+ * @error Invalid or incorrect Handle.
+ */
+native Float:BfReadFloat(Handle:bf);
+
+/**
+ * Reads a string from a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @param buffer Destination string buffer.
+ * @param maxlength Maximum length of output string buffer.
+ * @param line If true the buffer will be copied until it reaches a '\n' or a null terminator.
+ * @return Number of bytes written to the buffer. If the bitbuffer stream overflowed,
+ * that is, had no terminator before the end of the stream, then a negative
+ * number will be returned equal to the number of characters written to the
+ * buffer minus 1. The buffer will be null terminated regardless of the
+ * return value.
+ * @error Invalid or incorrect Handle.
+ */
+native BfReadString(Handle:bf, String:buffer[], maxlength, bool:line=false);
+
+/**
+ * Reads an entity from a readable bitbuffer (bf_read).
+ * @note This is a wrapper around BfReadShort().
+ *
+ * @param bf bf_read handle to read from.
+ * @return Entity index read.
+ * @error Invalid or incorrect Handle.
+ */
+native BfReadEntity(Handle:bf);
+
+/**
+ * Reads a bit angle from a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @param numBits Optional number of bits to use.
+ * @return Angle read.
+ * @error Invalid or incorrect Handle.
+ */
+native Float:BfReadAngle(Handle:bf, numBits=8);
+
+/**
+ * Reads a coordinate from a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @return Coordinate read.
+ * @error Invalid or incorrect Handle.
+ */
+native Float:BfReadCoord(Handle:bf);
+
+/**
+ * Reads a 3D vector of coordinates from a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @param coord Destination coordinate array.
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfReadVecCoord(Handle:bf, Float:coord[3]);
+
+/**
+ * Reads a 3D normal vector from a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @param vec Destination vector array.
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfReadVecNormal(Handle:bf, Float:vec[3]);
+
+/**
+ * Reads a 3D angle vector from a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @param angles Destination angle vector.
+ * @noreturn
+ * @error Invalid or incorrect Handle.
+ */
+native BfReadAngles(Handle:bf, Float:angles[3]);
+
+/**
+ * Returns the number of bytes left in a readable bitbuffer (bf_read).
+ *
+ * @param bf bf_read handle to read from.
+ * @return Number of bytes left unread.
+ * @error Invalid or incorrect Handle.
+ */
+native BfGetNumBytesLeft(Handle:bf);
diff --git a/sourcemod-1.5-dev/scripting/include/clientprefs.inc b/sourcemod-1.5-dev/scripting/include/clientprefs.inc
new file mode 100644
index 0000000..c6ac023
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/clientprefs.inc
@@ -0,0 +1,282 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2011 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _clientprefs_included
+ #endinput
+#endif
+#define _clientprefs_included
+
+/**
+ * Cookie access types for client viewing
+ */
+enum CookieAccess
+{
+ CookieAccess_Public, /**< Visible and Changeable by users */
+ CookieAccess_Protected, /**< Read only to users */
+ CookieAccess_Private, /**< Completely hidden cookie */
+};
+
+/**
+ * Cookie Prefab menu types
+ */
+enum CookieMenu
+{
+ CookieMenu_YesNo, /**< Yes/No menu with "yes"/"no" results saved into the cookie */
+ CookieMenu_YesNo_Int, /**< Yes/No menu with 1/0 saved into the cookie */
+ CookieMenu_OnOff, /**< On/Off menu with "on"/"off" results saved into the cookie */
+ CookieMenu_OnOff_Int, /**< On/Off menu with 1/0 saved into the cookie */
+};
+
+enum CookieMenuAction
+{
+ /**
+ * An option is being drawn for a menu.
+ *
+ * INPUT : Client index and data if available.
+ * OUTPUT: Buffer for rendering, maxlength of buffer.
+ */
+ CookieMenuAction_DisplayOption = 0,
+
+ /**
+ * A menu option has been selected.
+ *
+ * INPUT : Client index and any data if available.
+ */
+ CookieMenuAction_SelectOption = 1,
+};
+
+/**
+ * Note:
+ *
+ * A successful return value/result on any client prefs native only guarantees that the local cache has been updated.
+ * Database connection problems can still prevent the data from being permanently saved. Connection problems will be logged as
+ * errors by the clientprefs extension.
+ */
+
+/**
+ * Creates a new Client preference cookie.
+ *
+ * Handles returned by RegClientCookie can be closed via CloseHandle() when
+ * no longer needed.
+ *
+ * @param name Name of the new preference cookie.
+ * @param description Optional description of the preference cookie.
+ * @param access What CookieAccess level to assign to this cookie.
+ * @return A handle to the newly created cookie. If the cookie already
+ * exists, a handle to it will still be returned.
+ * @error Cookie name is blank.
+ */
+native Handle:RegClientCookie(const String:name[], const String:description[], CookieAccess:access);
+
+/**
+ * Searches for a Client preference cookie.
+ *
+ * Handles returned by FindClientCookie can be closed via CloseHandle() when
+ * no longer needed.
+ *
+ * @param name Name of cookie to find.
+ * @return A handle to the cookie if it is found. INVALID_HANDLE otherwise.
+ */
+native Handle:FindClientCookie(const String:name[]);
+
+/**
+ * Set the value of a Client preference cookie.
+ *
+ * @param client Client index.
+ * @param cookie Client preference cookie handle.
+ * @param value String value to set.
+ * @noreturn
+ * @error Invalid cookie handle or invalid client index.
+ */
+native SetClientCookie(client, Handle:cookie, const String:value[]);
+
+/**
+ * Retrieve the value of a Client preference cookie.
+ *
+ * @param client Client index.
+ * @param cookie Client preference cookie handle.
+ * @param buffer Copyback buffer for value.
+ * @param maxlen Maximum length of the buffer.
+ * @noreturn
+ * @error Invalid cookie handle or invalid client index.
+ */
+native GetClientCookie(client, Handle:cookie, String:buffer[], maxlen);
+
+/**
+ * Sets the value of a Client preference cookie based on an authID string.
+ *
+ * @param authID String Auth/STEAM ID of player to set.
+ * @param cookie Client preference cookie handle.
+ * @param value String value to set.
+ * @noreturn
+ * @error Invalid cookie handle.
+ */
+native SetAuthIdCookie(const String:authID[], Handle:cookie, const String:value[]);
+
+/**
+ * Checks if a clients cookies have been loaded from the database.
+ *
+ * @param client Client index.
+ * @return True if loaded, false otherwise.
+ * @error Invalid client index.
+ */
+native bool:AreClientCookiesCached(client);
+
+/**
+ * Called once a client's saved cookies have been loaded from the database.
+ *
+ * @param client Client index.
+ */
+forward OnClientCookiesCached(client);
+
+/**
+ * Cookie Menu Callback prototype
+ *
+ * @param client Client index.
+ * @param action CookieMenuAction being performed.
+ * @param info Info data passed.
+ * @param buffer Outbut buffer.
+ * @param maxlen Max length of the output buffer.
+ */
+functag public CookieMenuHandler(client, CookieMenuAction:action, any:info, String:buffer[], maxlen);
+
+/**
+ * Add a new prefab item to the client cookie settings menu.
+ *
+ * Note: This handles everything automatically and does not require a callback
+ *
+ * @param cookie Client preference cookie handle.
+ * @param type A CookieMenu prefab menu type.
+ * @param display Text to show on the menu.
+ * @param handler Optional handler callback for translations and output on selection
+ * @param info Info data to pass to the callback.
+ * @noreturn
+ * @error Invalid cookie handle.
+ */
+native SetCookiePrefabMenu(Handle:cookie, CookieMenu:type, const String:display[], CookieMenuHandler:handler=CookieMenuHandler:-1, info=0);
+
+/**
+ * Adds a new item to the client cookie settings menu.
+ *
+ * Note: This only adds the top level menu item. You need to handle any submenus from the callback.
+ *
+ * @param handler A MenuHandler callback function.
+ * @param info Data to pass to the callback.
+ * @param display Text to show on the menu.
+ * @noreturn
+ * @error Invalid cookie handle.
+ */
+native SetCookieMenuItem(CookieMenuHandler:handler, any:info, const String:display[]);
+
+/**
+ * Displays the settings menu to a client.
+ *
+ * @param client Client index.
+ * @noreturn
+ */
+native ShowCookieMenu(client);
+
+/**
+ * Gets a cookie iterator. Must be freed with CloseHandle().
+ *
+ * @return A new cookie iterator.
+ */
+native Handle:GetCookieIterator();
+
+/**
+ * Reads a cookie iterator, then advances to the next cookie if any.
+ *
+ * @param iter Cookie iterator Handle.
+ * @param name Name buffer.
+ * @param nameLen Name buffer size.
+ * @param access Access level of the cookie.
+ * @param desc Cookie description buffer.
+ * @param descLen Cookie description buffer size.
+ * @return True on success, false if there are no more commands.
+ */
+native bool:ReadCookieIterator(Handle:iter,
+ String:name[],
+ nameLen,
+ &CookieAccess:access,
+ String:desc[]="",
+ descLen=0);
+
+/**
+ * Returns the access level of a cookie
+ *
+ * @param cookie Client preference cookie handle.
+ * @return CookieAccess access level.
+ * @error Invalid cookie handle.
+ */
+native CookieAccess:GetCookieAccess(Handle:cookie);
+
+/**
+ * Returns the last updated timestamp for a client cookie
+ *
+ * @param client Client index.
+ * @param cookie Cookie handle.
+ * @return Last updated timestamp.
+ */
+native GetClientCookieTime(client, Handle:cookie);
+
+/**
+ * Do not edit below this line!
+ */
+public Extension:__ext_cprefs =
+{
+ name = "Client Preferences",
+ file = "clientprefs.ext",
+ autoload = 1,
+#if defined REQUIRE_EXTENSIONS
+ required = 1,
+#else
+ required = 0,
+#endif
+};
+
+#if !defined REQUIRE_EXTENSIONS
+public __ext_cprefs_SetNTVOptional()
+{
+ MarkNativeAsOptional("RegClientCookie");
+ MarkNativeAsOptional("FindClientCookie");
+ MarkNativeAsOptional("SetClientCookie");
+ MarkNativeAsOptional("GetClientCookie");
+ MarkNativeAsOptional("AreClientCookiesCached");
+ MarkNativeAsOptional("SetCookiePrefabMenu");
+ MarkNativeAsOptional("SetCookieMenuItem");
+ MarkNativeAsOptional("ShowCookieMenu");
+ MarkNativeAsOptional("GetCookieIterator");
+ MarkNativeAsOptional("ReadCookieIterator");
+ MarkNativeAsOptional("GetCookieAccess");
+ MarkNativeAsOptional("GetClientCookieTime");
+}
+#endif
diff --git a/sourcemod-1.5-dev/scripting/include/clients.inc b/sourcemod-1.5-dev/scripting/include/clients.inc
new file mode 100644
index 0000000..13381c3
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/clients.inc
@@ -0,0 +1,778 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _clients_included
+ #endinput
+#endif
+#define _clients_included
+
+/**
+ * Network flow directions.
+ */
+enum NetFlow
+{
+ NetFlow_Outgoing = 0, /**< Outgoing traffic */
+ NetFlow_Incoming, /**< Incoming traffic */
+ NetFlow_Both, /**< Both values added together */
+};
+
+/**
+ * MAXPLAYERS is not the same as MaxClients.
+ * MAXPLAYERS is a hardcoded value as an upper limit. MaxClients changes based on the server.
+ *
+ * Both GetMaxClients() and MaxClients are only available once the map is loaded, and should
+ * not be used in OnPluginStart().
+ */
+
+#define MAXPLAYERS 65 /**< Maximum number of players SourceMod supports */
+#define MAX_NAME_LENGTH 32 /**< Maximum buffer required to store a client name */
+
+public const MaxClients; /**< Maximum number of players the server supports (dynamic) */
+
+/**
+ * Called on client connection. If you return true, the client will be allowed in the server.
+ * If you return false (or return nothing), the client will be rejected. If the client is
+ * rejected by this forward or any other, OnClientDisconnect will not be called.
+ *
+ * Note: Do not write to rejectmsg if you plan on returning true. If multiple plugins write
+ * to the string buffer, it is not defined which plugin's string will be shown to the client,
+ * but it is guaranteed one of them will.
+ *
+ * @param client Client index.
+ * @param rejectmsg Buffer to store the rejection message when the connection is refused.
+ * @param maxlen Maximum number of characters for rejection buffer.
+ * @return True to validate client's connection, false to refuse it.
+ */
+forward bool:OnClientConnect(client, String:rejectmsg[], maxlen);
+
+/**
+ * Called once a client successfully connects. This callback is paired with OnClientDisconnect.
+ *
+ * @param client Client index.
+ * @noreturn
+ */
+forward OnClientConnected(client);
+
+/**
+ * Called when a client is entering the game.
+ *
+ * Whether a client has a steamid is undefined until OnClientAuthorized
+ * is called, which may occur either before or after OnClientPutInServer.
+ * Similarly, use OnClientPostAdminCheck() if you need to verify whether
+ * connecting players are admins.
+ *
+ * GetClientCount() will include clients as they are passed through this
+ * function, as clients are already in game at this point.
+ *
+ * @param client Client index.
+ * @noreturn
+ */
+forward OnClientPutInServer(client);
+
+/**
+ * Called when a client is disconnecting from the server.
+ *
+ * @param client Client index.
+ * @noreturn
+ */
+forward OnClientDisconnect(client);
+
+/**
+ * Called when a client is disconnected from the server.
+ *
+ * @param client Client index.
+ * @noreturn
+ */
+forward OnClientDisconnect_Post(client);
+
+/**
+ * Called when a client is sending a command.
+ *
+ * As of SourceMod 1.3, the client is guaranteed to be in-game.
+ * Use command listeners (console.inc) for more advanced hooks.
+ *
+ * @param client Client index.
+ * @param args Number of arguments.
+ * @noreturn
+ */
+forward Action:OnClientCommand(client, args);
+
+/**
+ * Called whenever the client's settings are changed.
+ *
+ * @param client Client index.
+ * @noreturn
+ */
+forward OnClientSettingsChanged(client);
+
+/**
+ * Called when a client receives a Steam ID. The state of a client's
+ * authorization as an admin is not guaranteed here. Use
+ * OnClientPostAdminCheck() if you need a client's admin status.
+ *
+ * This is called by bots, but the ID will be "BOT".
+ *
+ * @param client Client index.
+ * @param auth Client auth string.
+ * @noreturn
+ */
+forward OnClientAuthorized(client, const String:auth[]);
+
+/**
+ * Called once a client is authorized and fully in-game, but
+ * before admin checks are done. This can be used to override
+ * the default admin checks for a client. You should only use
+ * this for overriding; use OnClientPostAdminCheck() instead
+ * if you want notification.
+ *
+ * Note: If handled/blocked, PostAdminCheck must be signalled
+ * manually via NotifyPostAdminCheck().
+ *
+ * This callback is gauranteed to occur on all clients, and always
+ * after each OnClientPutInServer() call.
+ *
+ * @param client Client index.
+ * @return Plugin_Handled to block admin checks.
+ */
+forward Action:OnClientPreAdminCheck(client);
+
+/**
+ * Called directly before OnClientPostAdminCheck() as a method to
+ * alter administrative permissions before plugins perform final
+ * post-connect operations.
+ *
+ * In general, do not use this function unless you are specifically
+ * attempting to change access permissions. Use OnClientPostAdminCheck()
+ * instead if you simply want to perform post-connect authorization
+ * routines.
+ *
+ * See OnClientPostAdminCheck() for more information.
+ *
+ * @param client Client index.
+ * @noreturn
+ */
+forward OnClientPostAdminFilter(client);
+
+/**
+ * Called once a client is authorized and fully in-game, and
+ * after all post-connection authorizations have been performed.
+ *
+ * This callback is gauranteed to occur on all clients, and always
+ * after each OnClientPutInServer() call.
+ *
+ * @param client Client index.
+ * @noreturn
+ */
+forward OnClientPostAdminCheck(client);
+
+/**
+ * This function will be deprecated in a future release. Use the MaxClients variable instead.
+ *
+ * Returns the maximum number of clients allowed on the server. This may
+ * return 0 if called before OnMapStart(), and thus should not be called
+ * in OnPluginStart().
+ *
+ * You should not globally cache the value to GetMaxClients() because it can change from
+ * SourceTV or TF2's arena mode. Use the "MaxClients" dynamic variable documented at the
+ * top of this file.
+ *
+ * @return Maximum number of clients allowed.
+ */
+native GetMaxClients();
+
+/**
+ * Returns the maximum number of human players allowed on the server. This is
+ * a game-specific function used on newer games to limit the number of humans
+ * that can join a game and can be lower than MaxClients. It is the number often
+ * reflected in the server browser or when viewing the output of the status command.
+ * On unsupported games or modes without overrides, it will return the same value
+ * as MaxClients.
+ *
+ * You should not globally cache the value to GetMaxHumanPlayers() because it can change across
+ * game modes. You may still cache it locally.
+ *
+ * @return Maximum number of humans allowed.
+ */
+native GetMaxHumanPlayers();
+
+/**
+ * Returns the client count put in the server.
+ *
+ * @param inGameOnly If false connecting players are also counted.
+ * @return Client count in the server.
+ */
+native GetClientCount(bool:inGameOnly=true);
+
+/**
+ * Returns the client's name.
+ *
+ * @param client Player index.
+ * @param name Buffer to store the client's name.
+ * @param maxlen Maximum length of string buffer (includes NULL terminator).
+ * @return True on success, false otherwise.
+ * @error If the client is not connected an error will be thrown.
+ */
+native bool:GetClientName(client, String:name[], maxlen);
+
+/**
+ * Retrieves a client's IP address.
+ *
+ * @param client Player index.
+ * @param ip Buffer to store the client's ip address.
+ * @param maxlen Maximum length of string buffer (includes NULL terminator).
+ * @param remport Remove client's port from the ip string (true by default).
+ * @return True on success, false otherwise.
+ * @error If the client is not connected or the index is invalid.
+ */
+native bool:GetClientIP(client, String:ip[], maxlen, bool:remport=true);
+
+/**
+ * Retrieves a client's authentication string (SteamID).
+ *
+ * @param client Player index.
+ * @param auth Buffer to store the client's auth string.
+ * @param maxlen Maximum length of string buffer (includes NULL terminator).
+ * @param validate Check backend validation status.
+ * DO NOT PASS FALSE UNLESS YOU UNDERSTAND THE CONSEQUENCES,
+ * You WILL KNOW if you need to use this, MOST WILL NOT.
+ * @return True on success, false otherwise.
+ * @error If the client is not connected or the index is invalid.
+ */
+native bool:GetClientAuthString(client, String:auth[], maxlen, bool:validate=true);
+
+/**
+ * Returns the client's Steam account ID.
+ *
+ * @param client Client Index.
+ * @param validate Check backend validation status.
+ * DO NOT PASS FALSE UNLESS YOU UNDERSTAND THE CONSEQUENCES,
+ * You WILL KNOW if you need to use this, MOST WILL NOT.
+ * @return Steam account ID or 0 if not available.
+ * @error If the client is not connected or the index is invalid.
+ */
+native GetSteamAccountID(client, bool:validate=true);
+
+/**
+ * Retrieves a client's user id, which is an index incremented for every client
+ * that joins the server.
+ *
+ * @param client Player index.
+ * @return User id of the client.
+ * @error If the client is not connected or the index is invalid.
+ */
+native GetClientUserId(client);
+
+/**
+ * Returns if a certain player is connected.
+ *
+ * @param client Player index.
+ * @return True if player is connected to the server, false otherwise.
+ */
+native bool:IsClientConnected(client);
+
+/**
+ * Returns if a certain player has entered the game.
+ *
+ * @param client Player index (index does not have to be connected).
+ * @return True if player has entered the game, false otherwise.
+ * @error Invalid client index.
+ */
+native bool:IsClientInGame(client);
+
+/**
+ * Returns if a client is in the "kick queue" (i.e. the client will be kicked
+ * shortly and thus they should not appear as valid).
+ *
+ * @param client Player index (must be connected).
+ * @return True if in the kick queue, false otherwise.
+ * @error Invalid client index.
+ */
+native bool:IsClientInKickQueue(client);
+
+/**
+ * Backwards compatibility stock - use IsClientInGame
+ * @deprecated Renamed to IsClientInGame
+ */
+#pragma deprecated Use IsClientInGame() instead
+stock bool:IsPlayerInGame(client)
+{
+ return IsClientInGame(client);
+}
+
+/**
+ * Returns if a certain player has been authenticated.
+ *
+ * @param client Player index.
+ * @return True if player has been authenticated, false otherwise.
+ */
+native bool:IsClientAuthorized(client);
+
+/**
+ * Returns if a certain player is a fake client.
+ *
+ * @param client Player index.
+ * @return True if player is a fake client, false otherwise.
+ */
+native bool:IsFakeClient(client);
+
+/**
+ * Returns if a certain player is the SourceTV bot.
+ *
+ * @param client Player index.
+ * @return True if player is the SourceTV bot, false otherwise.
+ */
+native bool:IsClientSourceTV(client);
+
+/**
+ * Returns if a certain player is the Replay bot.
+ *
+ * @param client Player index.
+ * @return True if player is the Replay bot, false otherwise.
+ */
+native bool:IsClientReplay(client);
+
+/**
+ * Returns if a certain player is an observer/spectator.
+ *
+ * @param client Player index.
+ * @return True if player is an obverser, false otherwise.
+ */
+native bool:IsClientObserver(client);
+
+/**
+ * Returns if the client is alive or dead.
+ *
+ * Note: This function was originally in SDKTools and was moved to core.
+ *
+ * @param client Player's index.
+ * @return True if the client is alive, false otherwise.
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native bool:IsPlayerAlive(client);
+
+/**
+ * Retrieves values from client replicated keys.
+ *
+ * @param client Player's index.
+ * @param key Key string.
+ * @param value Buffer to store value.
+ * @param maxlen Maximum length of valve (UTF-8 safe).
+ * @return True on success, false otherwise.
+ * @error Invalid client index, or client not connected.
+ */
+native bool:GetClientInfo(client, const String:key[], String:value[], maxlen);
+
+/**
+ * Retrieves a client's team index.
+ *
+ * @param client Player's index.
+ * @return Team index the client is on (mod specific).
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native GetClientTeam(client);
+
+/**
+ * Sets a client's AdminId.
+ *
+ * @param client Player's index.
+ * @param id AdminId to set. INVALID_ADMIN_ID removes admin permissions.
+ * @param temp True if the id should be freed on disconnect.
+ * @noreturn
+ * @error Invalid client index, client not connected, or bogus AdminId.
+ */
+native SetUserAdmin(client, AdminId:id, bool:temp=false);
+
+/**
+ * Retrieves a client's AdminId.
+ *
+ * @param client Player's index.
+ * @return AdminId of the client, or INVALID_ADMIN_ID if none.
+ * @error Invalid client index, or client not connected.
+ */
+native AdminId:GetUserAdmin(client);
+
+/**
+ * Sets access flags on a client. If the client is not an admin,
+ * a temporary, anonymous AdminId is given.
+ *
+ * @param client Player's index.
+ * @param ... Flags to set on the client.
+ * @noreturn
+ * @error Invalid client index, or client not connected.
+ */
+native AddUserFlags(client, AdminFlag:...);
+
+/**
+ * Removes flags from a client. If the client is not an admin,
+ * this has no effect.
+ *
+ * @param client Player's index.
+ * @param ... Flags to remove from the client.
+ * @noreturn
+ * @error Invalid client index, or client not connected.
+ */
+native RemoveUserFlags(client, AdminFlag:...);
+
+/**
+ * Sets access flags on a client using bits instead of flags. If the
+ * client is not an admin, and flags not 0, a temporary, anonymous AdminId is given.
+ *
+ * @param client Player's index.
+ * @param flags Bitstring of flags to set on client.
+ * @noreturn
+ */
+native SetUserFlagBits(client, flags);
+
+/**
+ * Returns client access flags. If the client is not an admin,
+ * the result is always 0.
+ *
+ * @param client Player's index.
+ * @return Flags
+ * @error Invalid client index, or client not connected.
+ */
+native GetUserFlagBits(client);
+
+/**
+ * Returns whether a user can target another user.
+ * This is a helper function for CanAdminTarget.
+ *
+ * @param client Player's index.
+ * @param target Target player's index.
+ * @return True if target is targettable by the player, false otherwise.
+ * @error Invalid or unconnected player indexers.
+ */
+native bool:CanUserTarget(client, target);
+
+/**
+ * Runs through the Core-defined admin authorization checks on a player.
+ * Has no effect if the player is already an admin.
+ *
+ * Note: This function is based on the internal cache only.
+ *
+ * @param client Client index.
+ * @return True if access was changed, false if it did not.
+ * @error Invalid client index or client not in-game AND authorized.
+ */
+native bool:RunAdminCacheChecks(client);
+
+/**
+ * Signals that a player has completed post-connection admin checks.
+ * Has no effect if the player has already had this event signalled.
+ *
+ * Note: This must be sent even if no admin id was assigned.
+ *
+ * @param client Client index.
+ * @noreturn
+ * @error Invalid client index or client not in-game AND authorized.
+ */
+native NotifyPostAdminCheck(client);
+
+/**
+ * Creates a fake client.
+ *
+ * @param name Name to use.
+ * @return Client index on success, 0 otherwise.
+ */
+native CreateFakeClient(const String:name[]);
+
+/**
+ * Sets a convar value on a fake client.
+ *
+ * @param client Client index.
+ * @param cvar ConVar name.
+ * @param value ConVar value.
+ * @noreturn
+ * @error Invalid client index, client not connected,
+ * or client not a fake client.
+ */
+native SetFakeClientConVar(client, const String:cvar[], const String:value[]);
+
+/**
+ * Returns the client's health.
+ *
+ * @param client Player's index.
+ * @return Health value.
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native GetClientHealth(client);
+
+/**
+ * Returns the client's model name.
+ *
+ * @param client Player's index.
+ * @param model Buffer to store the client's model name.
+ * @param maxlen Maximum length of string buffer (includes NULL terminator).
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native GetClientModel(client, String:model[], maxlen);
+
+/**
+ * Returns the client's weapon name.
+ *
+ * @param client Player's index.
+ * @param weapon Buffer to store the client's weapon name.
+ * @param maxlen Maximum length of string buffer (includes NULL terminator).
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native GetClientWeapon(client, String:weapon[], maxlen);
+
+/**
+ * Returns the client's max size vector.
+ *
+ * @param client Player's index.
+ * @param vec Destination vector to store the client's max size.
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native GetClientMaxs(client, Float:vec[3]);
+
+/**
+ * Returns the client's min size vector.
+ *
+ * @param client Player's index.
+ * @param vec Destination vector to store the client's min size.
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native GetClientMins(client, Float:vec[3]);
+
+/**
+ * Returns the client's position angle.
+ *
+ * @param client Player's index.
+ * @param ang Destination vector to store the client's position angle.
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native GetClientAbsAngles(client, Float:ang[3]);
+
+/**
+ * Returns the client's origin vector.
+ *
+ * @param client Player's index.
+ * @param vec Destination vector to store the client's origin vector.
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native GetClientAbsOrigin(client, Float:vec[3]);
+
+/**
+ * Returns the client's armor.
+ *
+ * @param client Player's index.
+ * @return Armor value.
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native GetClientArmor(client);
+
+/**
+ * Returns the client's death count.
+ *
+ * @param client Player's index.
+ * @return Death count.
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native GetClientDeaths(client);
+
+/**
+ * Returns the client's frag count.
+ *
+ * @param client Player's index.
+ * @return Frag count.
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native GetClientFrags(client);
+
+/**
+ * Returns the client's send data rate in bytes/sec.
+ *
+ * @param client Player's index.
+ * @return Data rate.
+ * @error Invalid client index, client not connected, or fake client.
+ */
+native GetClientDataRate(client);
+
+/**
+ * Returns if a client is timing out
+ *
+ * @param client Player's index.
+ * @return True if client is timing out, false otherwise.
+ * @error Invalid client index, client not connected, or fake client.
+ */
+native bool:IsClientTimingOut(client);
+
+/**
+ * Returns the client's connection time in seconds.
+ *
+ * @param client Player's index.
+ * @return Connection time.
+ * @error Invalid client index, client not connected, or fake client.
+ */
+native Float:GetClientTime(client);
+
+/**
+ * Returns the client's current latency (RTT), more accurate than GetAvgLatency but jittering.
+ *
+ * @param client Player's index.
+ * @param flow Traffic flowing direction.
+ * @return Latency, or -1 if network info is not available.
+ * @error Invalid client index, client not connected, or fake client.
+ */
+native Float:GetClientLatency(client, NetFlow:flow);
+
+/**
+ * Returns the client's average packet latency in seconds.
+ *
+ * @param client Player's index.
+ * @param flow Traffic flowing direction.
+ * @return Latency, or -1 if network info is not available.
+ * @error Invalid client index, client not connected, or fake client.
+ */
+native Float:GetClientAvgLatency(client, NetFlow:flow);
+
+/**
+ * Returns the client's average packet loss, values go from 0 to 1 (for percentages).
+ *
+ * @param client Player's index.
+ * @param flow Traffic flowing direction.
+ * @return Average packet loss, or -1 if network info is not available.
+ * @error Invalid client index, client not connected, or fake client.
+ */
+native Float:GetClientAvgLoss(client, NetFlow:flow);
+
+/**
+ * Returns the client's average packet choke, values go from 0 to 1 (for percentages).
+ *
+ * @param client Player's index.
+ * @param flow Traffic flowing direction.
+ * @return Average packet loss, or -1 if network info is not available.
+ * @error Invalid client index, client not connected, or fake client.
+ */
+native Float:GetClientAvgChoke(client, NetFlow:flow);
+
+/**
+ * Returns the client's data flow in bytes/sec.
+ *
+ * @param client Player's index.
+ * @param flow Traffic flowing direction.
+ * @return Data flow.
+ * @error Invalid client index, client not connected, or fake client.
+ */
+native Float:GetClientAvgData(client, NetFlow:flow);
+
+/**
+ * Returns the client's average packet frequency in packets/sec.
+ *
+ * @param client Player's index.
+ * @param flow Traffic flowing direction.
+ * @return Packet frequency.
+ * @error Invalid client index, client not connected, or fake client.
+ */
+native Float:GetClientAvgPackets(client, NetFlow:flow);
+
+/**
+ * Translates an userid index to the real player index.
+ *
+ * @param userid Userid value.
+ * @return Client value.
+ * @error Returns 0 if invalid userid.
+ */
+native GetClientOfUserId(userid);
+
+/**
+ * Disconnects a client from the server as soon as the next frame starts.
+ *
+ * Note: Originally, KickClient() was immediate. The delay was introduced
+ * because despite warnings, plugins were using it in ways that would crash.
+ * The new safe version can break cases that rely on immediate disconnects,
+ * but ensures that plugins do not accidentally cause crashes.
+ *
+ * If you need immediate disconnects, use KickClientEx().
+ *
+ * Note: IsClientInKickQueue() will return true before the kick occurs.
+ *
+ * @param client Client index.
+ * @param format Optional formatting rules for disconnect reason.
+ * Note that a period is automatically appended to the string by the engine.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ * @error Invalid client index, or client not connected.
+ */
+native KickClient(client, const String:format[]="", any:...);
+
+/**
+ * Immediately disconnects a client from the server.
+ *
+ * Kicking clients from certain events or callbacks may cause crashes. If in
+ * doubt, create a short (0.1 second) timer to kick the client in the next
+ * available frame.
+ *
+ * @param client Client index.
+ * @param format Optional formatting rules for disconnect reason.
+ * Note that a period is automatically appended to the string by the engine.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ * @error Invalid client index, or client not connected.
+ */
+native KickClientEx(client, const String:format[]="", any:...);
+
+/**
+ * Changes a client's team through the mod's generic team changing function.
+ * On CS:S, this will kill the player.
+ *
+ * @param client Client index.
+ * @param team Mod-specific team index.
+ * @noreturn
+ * @error Invalid client index, client not connected, or lack of
+ * mod support.
+ */
+native ChangeClientTeam(client, team);
+
+/**
+ * Returns the clients unique serial identifier.
+ *
+ * @param client Client index.
+ * @return Serial number.
+ */
+native GetClientSerial(client);
+
+/**
+ * Returns the client index by its serial number.
+ *
+ * @param serial Serial number.
+ * @return Client index, or 0 for invalid serial.
+ */
+native GetClientFromSerial(serial);
+
diff --git a/sourcemod-1.5-dev/scripting/include/commandfilters.inc b/sourcemod-1.5-dev/scripting/include/commandfilters.inc
new file mode 100644
index 0000000..6ea447c
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/commandfilters.inc
@@ -0,0 +1,165 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _commandfilters_included
+ #endinput
+#endif
+#define _commandfilters_included
+
+#define MAX_TARGET_LENGTH 64
+
+#define COMMAND_FILTER_ALIVE (1<<0) /**< Only allow alive players */
+#define COMMAND_FILTER_DEAD (1<<1) /**< Only filter dead players */
+#define COMMAND_FILTER_CONNECTED (1<<2) /**< Allow players not fully in-game */
+#define COMMAND_FILTER_NO_IMMUNITY (1<<3) /**< Ignore immunity rules */
+#define COMMAND_FILTER_NO_MULTI (1<<4) /**< Do not allow multiple target patterns */
+#define COMMAND_FILTER_NO_BOTS (1<<5) /**< Do not allow bots to be targetted */
+
+#define COMMAND_TARGET_NONE 0 /**< No target was found */
+#define COMMAND_TARGET_NOT_ALIVE -1 /**< Single client is not alive */
+#define COMMAND_TARGET_NOT_DEAD -2 /**< Single client is not dead */
+#define COMMAND_TARGET_NOT_IN_GAME -3 /**< Single client is not in game */
+#define COMMAND_TARGET_IMMUNE -4 /**< Single client is immune */
+#define COMMAND_TARGET_EMPTY_FILTER -5 /**< A multi-filter (such as @all) had no targets */
+#define COMMAND_TARGET_NOT_HUMAN -6 /**< Target was not human */
+#define COMMAND_TARGET_AMBIGUOUS -7 /**< Partial name had too many targets */
+
+/**
+ * Processes a generic command target string, and resolves it to a list
+ * of clients or one client, based on filtering rules and a pattern.
+ *
+ * Note that you should use LoadTranslations("common.phrases") in OnPluginStart(),
+ * as that file is guaranteed to contain all of the translatable phrases that
+ * ProcessTargetString() will return.
+ *
+ * @param pattern Pattern to find clients against.
+ * @param admin Admin performing the action, or 0 if the server.
+ * @param targets Array to hold targets.
+ * @param max_targets Maximum size of the targets array.
+ * @param filter_flags Filter flags.
+ * @param target_name Buffer to store the target name.
+ * @param tn_maxlength Maximum length of the target name buffer.
+ * @param tn_is_ml OUTPUT: Will be true if the target name buffer is an ML phrase,
+ * false if it is a normal string.
+ * @return If a multi-target pattern was used, the number of clients found
+ * is returned. If a single-target pattern was used, 1 is returned
+ * if one valid client is found. Otherwise, a COMMAND_TARGET reason
+ * for failure is returned.
+ */
+native ProcessTargetString(const String:pattern[],
+ admin,
+ targets[],
+ max_targets,
+ filter_flags,
+ String:target_name[],
+ tn_maxlength,
+ &bool:tn_is_ml);
+
+/**
+ * Replies to a client with a given message describing a targetting
+ * failure reason.
+ *
+ * Note: The translation phrases are found in common.phrases.txt.
+ *
+ * @param client Client index, or 0 for server.
+ * @param reason COMMAND_TARGET reason.
+ * @noreturn
+ */
+stock ReplyToTargetError(client, reason)
+{
+ switch (reason)
+ {
+ case COMMAND_TARGET_NONE:
+ {
+ ReplyToCommand(client, "[SM] %t", "No matching client");
+ }
+ case COMMAND_TARGET_NOT_ALIVE:
+ {
+ ReplyToCommand(client, "[SM] %t", "Target must be alive");
+ }
+ case COMMAND_TARGET_NOT_DEAD:
+ {
+ ReplyToCommand(client, "[SM] %t", "Target must be dead");
+ }
+ case COMMAND_TARGET_NOT_IN_GAME:
+ {
+ ReplyToCommand(client, "[SM] %t", "Target is not in game");
+ }
+ case COMMAND_TARGET_IMMUNE:
+ {
+ ReplyToCommand(client, "[SM] %t", "Unable to target");
+ }
+ case COMMAND_TARGET_EMPTY_FILTER:
+ {
+ ReplyToCommand(client, "[SM] %t", "No matching clients");
+ }
+ case COMMAND_TARGET_NOT_HUMAN:
+ {
+ ReplyToCommand(client, "[SM] %t", "Cannot target bot");
+ }
+ case COMMAND_TARGET_AMBIGUOUS:
+ {
+ ReplyToCommand(client, "[SM] %t", "More than one client matched");
+ }
+ }
+}
+
+/**
+ * Adds clients to a multi-target filter.
+ *
+ * @param pattern Pattern name.
+ * @param clients Array to fill with unique, valid client indexes.
+ * @return True if pattern was recognized, false otherwise.
+ */
+functag public bool:MultiTargetFilter(const String:pattern[], Handle:clients);
+
+/**
+ * Adds a multi-target filter function for ProcessTargetString().
+ *
+ * @param pattern Pattern to match (case sensitive).
+ * @param filter Filter function.
+ * @param phrase Descriptive phrase to display on successful match.
+ * @param phraseIsML True if phrase is multi-lingual, false otherwise.
+ * @noreturn
+ */
+native AddMultiTargetFilter(const String:pattern[], MultiTargetFilter:filter,
+ const String:phrase[], bool:phraseIsML);
+
+/**
+ * Removes a multi-target filter function from ProcessTargetString().
+ *
+ * @param pattern Pattern to match (case sensitive).
+ * @param filter Filter function.
+ * @noreturn
+ */
+native RemoveMultiTargetFilter(const String:pattern[], MultiTargetFilter:filter);
+
diff --git a/sourcemod-1.5-dev/scripting/include/console.inc b/sourcemod-1.5-dev/scripting/include/console.inc
new file mode 100644
index 0000000..d89bcbc
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/console.inc
@@ -0,0 +1,971 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _console_included
+ #endinput
+#endif
+#define _console_included
+
+#define INVALID_FCVAR_FLAGS (-1)
+
+/**
+ * Console variable bound values used with Get/SetConVarBounds()
+ */
+enum ConVarBounds
+{
+ ConVarBound_Upper = 0,
+ ConVarBound_Lower
+};
+
+/**
+ * Console variable query helper values.
+ */
+enum QueryCookie
+{
+ QUERYCOOKIE_FAILED = 0,
+};
+
+/**
+ * Reply sources for commands.
+ */
+enum ReplySource
+{
+ SM_REPLY_TO_CONSOLE = 0,
+ SM_REPLY_TO_CHAT = 1,
+};
+
+/**
+ * Console variable query result values.
+ */
+enum ConVarQueryResult
+{
+ ConVarQuery_Okay = 0, /**< Retrieval of client convar value was successful. */
+ ConVarQuery_NotFound, /**< Client convar was not found. */
+ ConVarQuery_NotValid, /**< A console command with the same name was found, but there is no convar. */
+ ConVarQuery_Protected /**< Client convar was found, but it is protected. The server cannot retrieve its value. */
+};
+
+/**
+ * @section Flags for console commands and console variables. The descriptions
+ * for each constant come directly from the Source SDK.
+ */
+#define FCVAR_NONE 0 /**< The default, no flags at all */
+#define FCVAR_UNREGISTERED (1<<0) /**< If this is set, don't add to linked list, etc. */
+#define FCVAR_LAUNCHER (1<<1) /**< Defined by launcher. */
+#define FCVAR_GAMEDLL (1<<2) /**< Defined by the game DLL. */
+#define FCVAR_CLIENTDLL (1<<3) /**< Defined by the client DLL. */
+#define FCVAR_MATERIAL_SYSTEM (1<<4) /**< Defined by the material system. */
+#define FCVAR_PROTECTED (1<<5) /**< It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value. */
+#define FCVAR_SPONLY (1<<6) /**< This cvar cannot be changed by clients connected to a multiplayer server. */
+#define FCVAR_ARCHIVE (1<<7) /**< Set to cause it to be saved to vars.rc */
+#define FCVAR_NOTIFY (1<<8) /**< Notifies players when changed. */
+#define FCVAR_USERINFO (1<<9) /**< Changes the client's info string. */
+#define FCVAR_PRINTABLEONLY (1<<10) /**< This cvar's string cannot contain unprintable characters (e.g., used for player name, etc.) */
+#define FCVAR_UNLOGGED (1<<11) /**< If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log */
+#define FCVAR_NEVER_AS_STRING (1<<12) /**< Never try to print that cvar. */
+#define FCVAR_REPLICATED (1<<13) /**< Server setting enforced on clients. */
+#define FCVAR_CHEAT (1<<14) /**< Only useable in singleplayer / debug / multiplayer & sv_cheats */
+#define FCVAR_STUDIORENDER (1<<15) /**< Defined by the studiorender system. */
+#define FCVAR_DEMO (1<<16) /**< Record this cvar when starting a demo file. */
+#define FCVAR_DONTRECORD (1<<17) /**< Don't record these command in demo files. */
+#define FCVAR_PLUGIN (1<<18) /**< Defined by a 3rd party plugin. */
+#define FCVAR_DATACACHE (1<<19) /**< Defined by the datacache system. */
+#define FCVAR_TOOLSYSTEM (1<<20) /**< Defined by an IToolSystem library */
+#define FCVAR_FILESYSTEM (1<<21) /**< Defined by the file system. */
+#define FCVAR_NOT_CONNECTED (1<<22) /**< Cvar cannot be changed by a client that is connected to a server. */
+#define FCVAR_SOUNDSYSTEM (1<<23) /**< Defined by the soundsystem library. */
+#define FCVAR_ARCHIVE_XBOX (1<<24) /**< Cvar written to config.cfg on the Xbox. */
+#define FCVAR_INPUTSYSTEM (1<<25) /**< Defined by the inputsystem DLL. */
+#define FCVAR_NETWORKSYSTEM (1<<26) /**< Defined by the network system. */
+#define FCVAR_VPHYSICS (1<<27) /**< Defined by vphysics. */
+
+/**
+ * @endsection
+ */
+
+/**
+ * Executes a server command as if it were on the server console (or RCON)
+ *
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+native ServerCommand(const String:format[], any:...);
+
+/**
+ * Executes a server command as if it were on the server console (or RCON)
+ * and stores the printed text into buffer.
+ *
+ * Warning: This calls ServerExecute internally and may have issues if
+ * certain commands are in the buffer, only use when you really need
+ * the response.
+ * Also, on L4D2 this will not print the command output to the server console.
+ *
+ * @param buffer String to store command result into.
+ * @param maxlen Length of buffer.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+native ServerCommandEx(String:buffer[], maxlen, const String:format[], any:...);
+
+/**
+ * Inserts a server command at the beginning of the server command buffer.
+ *
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+native InsertServerCommand(const String:format[], any:...);
+
+/**
+ * Executes every command in the server's command buffer, rather than once per frame.
+ *
+ * @noreturn
+ */
+native ServerExecute();
+
+/**
+ * Executes a client command. Note that this will not work on clients unless
+ * they have cl_restrict_server_commands set to 0.
+ *
+ * @param client Index of the client.
+ * @param fmt Format of the client command.
+ * @param ... Format parameters
+ * @noreturn
+ * @error Invalid client index, or client not connected.
+ */
+native ClientCommand(client, const String:fmt[], any:...);
+
+/**
+ * Executes a client command on the server without being networked.
+ *
+ * FakeClientCommand() overwrites the command tokenization buffer. This can
+ * cause undesired effects because future calls to GetCmdArg* will return
+ * data from the FakeClientCommand(), not the parent command. If you are in
+ * a hook where this matters (for example, a "say" hook), you should use
+ * FakeClientCommandEx() instead.
+ *
+ * @param client Index of the client.
+ * @param fmt Format of the client command.
+ * @param ... Format parameters
+ * @noreturn
+ * @error Invalid client index, or client not connected.
+ */
+native FakeClientCommand(client, const String:fmt[], any:...);
+
+/**
+ * Executes a client command on the server without being networked. The
+ * execution of the client command is delayed by one frame to prevent any
+ * re-entrancy issues that might surface with FakeClientCommand().
+ *
+ * @param client Index of the client.
+ * @param fmt Format of the client command.
+ * @param ... Format parameters
+ * @noreturn
+ * @error Invalid client index, or client not connected.
+ */
+native FakeClientCommandEx(client, const String:fmt[], any:...);
+
+/**
+ * Sends a message to the server console.
+ *
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+native PrintToServer(const String:format[], any:...);
+
+/**
+ * Sends a message to a client's console.
+ *
+ * @param client Client index.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ * @error If the client is not connected an error will be thrown.
+ */
+native PrintToConsole(client, const String:format[], any:...);
+
+/**
+ * Reples to a message in a command.
+ *
+ * A client index of 0 will use PrintToServer().
+ * If the command was from the console, PrintToConsole() is used.
+ * If the command was from chat, PrintToChat() is used.
+ *
+ * @param client Client index, or 0 for server.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ * @error If the client is not connected or invalid.
+ */
+native ReplyToCommand(client, const String:format[], any:...);
+
+/**
+ * Returns the current reply source of a command.
+ *
+ * @return ReplySource value.
+ */
+native ReplySource:GetCmdReplySource();
+
+/**
+ * Sets the current reply source of a command.
+ *
+ * Only use this if you know what you are doing. You should save the old value
+ * and restore it once you are done.
+ *
+ * @param source New ReplySource value.
+ * @return Old ReplySource value.
+ */
+native ReplySource:SetCmdReplySource(ReplySource:source);
+
+/**
+ * Returns whether the current say hook is a chat trigger.
+ *
+ * This function is only meaningful inside say or say_team hooks.
+ *
+ * @return True if a chat trigger, false otherwise.
+ */
+native bool:IsChatTrigger();
+
+/**
+ * Displays usage of an admin command to users depending on the
+ * setting of the sm_show_activity cvar. All users receive a message
+ * in their chat text, except for the originating client, who receives
+ * the message based on the current ReplySource.
+ *
+ * @param client Client index doing the action, or 0 for server.
+ * @param tag Tag to prepend to the message.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ * @error
+ */
+native ShowActivity2(client, const String:tag[], const String:format[], any:...);
+
+/**
+ * Displays usage of an admin command to users depending on the
+ * setting of the sm_show_activity cvar.
+ *
+ * This version does not display a message to the originating client
+ * if used from chat triggers or menus. If manual replies are used
+ * for these cases, then this function will suffice. Otherwise,
+ * ShowActivity2() is slightly more useful.
+ *
+ * @param client Client index doing the action, or 0 for server.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ * @error
+ */
+native ShowActivity(client, const String:format[], any:...);
+
+/**
+ * Same as ShowActivity(), except the tag parameter is used instead of
+ * "[SM] " (note that you must supply any spacing).
+ *
+ * @param client Client index doing the action, or 0 for server.
+ * @param tag Tag to display with.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ * @error
+ */
+native ShowActivityEx(client, const String:tag[], const String:format[], any:...);
+
+/**
+ * Given an originating client and a target client, returns the string
+ * that describes the originating client according to the sm_show_activity cvar.
+ *
+ * For example, "ADMIN", "PLAYER", or a player's name could be placed in this buffer.
+ *
+ * @param client Originating client; may be 0 for server console.
+ * @param target Targeted client.
+ * @param namebuf Name buffer.
+ * @param maxlength Maximum size of the name buffer.
+ * @return True if activity should be shown. False otherwise. In either
+ * case, the name buffer is filled. The return value can be used
+ * to broadcast a "safe" name to all players regardless of the
+ * sm_show_activity filters.
+ * @error Invalid client index or client not connected.
+ */
+native FormatActivitySource(client, target, const String:namebuf[], maxlength);
+
+/**
+ * Called when a server-only command is invoked.
+ *
+ * @param args Number of arguments that were in the argument string.
+ * @return An Action value. Not handling the command
+ * means that Source will report it as "not found."
+ */
+functag public Action:SrvCmd(args);
+
+/**
+ * Creates a server-only console command, or hooks an already existing one.
+ *
+ * Server commands are case sensitive.
+ *
+ * @param cmd Name of the command to hook or create.
+ * @param callback A function to use as a callback for when the command is invoked.
+ * @param description Optional description to use for command creation.
+ * @param flags Optional flags to use for command creation.
+ * @noreturn
+ * @error Command name is the same as an existing convar.
+ */
+native RegServerCmd(const String:cmd[], SrvCmd:callback, const String:description[]="", flags=0);
+
+/**
+ * Called when a generic console command is invoked.
+ *
+ * @param client Index of the client, or 0 from the server.
+ * @param args Number of arguments that were in the argument string.
+ * @return An Action value. Not handling the command
+ * means that Source will report it as "not found."
+ */
+functag public Action:ConCmd(client, args);
+
+/**
+ * Creates a console command, or hooks an already existing one.
+ *
+ * Console commands are case sensitive. However, if the command already exists in the game,
+ * a client may enter the command in any case. SourceMod corrects for this automatically,
+ * and you should only hook the "real" version of the command.
+ *
+ * @param cmd Name of the command to hook or create.
+ * @param callback A function to use as a callback for when the command is invoked.
+ * @param description Optional description to use for command creation.
+ * @param flags Optional flags to use for command creation.
+ * @noreturn
+ * @error Command name is the same as an existing convar.
+ */
+native RegConsoleCmd(const String:cmd[], ConCmd:callback, const String:description[]="", flags=0);
+
+/**
+ * Creates a console command as an administrative command. If the command does not exist,
+ * it is created. When this command is invoked, the access rights of the player are
+ * automatically checked before allowing it to continue.
+ *
+ * Admin commands are case sensitive from both the client and server.
+ *
+ * @param cmd String containing command to register.
+ * @param callback A function to use as a callback for when the command is invoked.
+ * @param adminflags Administrative flags (bitstring) to use for permissions.
+ * @param description Optional description to use for help.
+ * @param group String containing the command group to use. If empty,
+ * the plugin's filename will be used instead.
+ * @param flags Optional console flags.
+ * @noreturn
+ * @error Command name is the same as an existing convar.
+ */
+native RegAdminCmd(const String:cmd[],
+ ConCmd:callback,
+ adminflags,
+ const String:description[]="",
+ const String:group[]="",
+ flags=0);
+
+/**
+ * Returns the number of arguments from the current console or server command.
+ * @note Unlike the HL2 engine call, this does not include the command itself.
+ *
+ * @return Number of arguments to the current command.
+ */
+native GetCmdArgs();
+
+/**
+ * Retrieves a command argument given its index, from the current console or
+ * server command.
+ * @note Argument indexes start at 1; 0 retrieves the command name.
+ *
+ * @param argnum Argument number to retrieve.
+ * @param buffer Buffer to use for storing the string.
+ * @param maxlength Maximum length of the buffer.
+ * @return Length of string written to buffer.
+ */
+native GetCmdArg(argnum, String:buffer[], maxlength);
+
+/**
+ * Retrieves the entire command argument string in one lump from the current
+ * console or server command.
+ *
+ * @param buffer Buffer to use for storing the string.
+ * @param maxlength Maximum length of the buffer.
+ * @return Length of string written to buffer.
+ */
+native GetCmdArgString(String:buffer[], maxlength);
+
+/**
+ * Creates a new console variable.
+ *
+ * @param name Name of new convar.
+ * @param defaultValue String containing the default value of new convar.
+ * @param description Optional description of the convar.
+ * @param flags Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details.
+ * @param hasMin Optional boolean that determines if the convar has a minimum value.
+ * @param min Minimum floating point value that the convar can have if hasMin is true.
+ * @param hasMax Optional boolean that determines if the convar has a maximum value.
+ * @param max Maximum floating point value that the convar can have if hasMax is true.
+ * @return A handle to the newly created convar. If the convar already exists, a handle to it will still be returned.
+ * @error Convar name is blank or is the same as an existing console command.
+ */
+native Handle:CreateConVar(const String:name[], const String:defaultValue[], const String:description[]="", flags=0, bool:hasMin=false, Float:min=0.0, bool:hasMax=false, Float:max=0.0);
+
+/**
+ * Searches for a console variable.
+ *
+ * @param name Name of convar to find.
+ * @return A handle to the convar if it is found. INVALID_HANDLE otherwise.
+ */
+native Handle:FindConVar(const String:name[]);
+
+/**
+ * Called when a console variable's value is changed.
+ *
+ * @param convar Handle to the convar that was changed.
+ * @param oldValue String containing the value of the convar before it was changed.
+ * @param newValue String containing the new value of the convar.
+ * @noreturn
+ */
+functag public ConVarChanged(Handle:convar, const String:oldValue[], const String:newValue[]);
+
+/**
+ * Creates a hook for when a console variable's value is changed.
+ *
+ * @param convar Handle to the convar.
+ * @param callback An OnConVarChanged function pointer.
+ * @noreturn
+ * @error Invalid or corrupt Handle or invalid callback function.
+ */
+native HookConVarChange(Handle:convar, ConVarChanged:callback);
+
+/**
+ * Removes a hook for when a console variable's value is changed.
+ *
+ * @param convar Handle to the convar.
+ * @param callback An OnConVarChanged function pointer.
+ * @noreturn
+ * @error Invalid or corrupt Handle, invalid callback function, or no active hook on convar.
+ */
+native UnhookConVarChange(Handle:convar, ConVarChanged:callback);
+
+/**
+ * Returns the boolean value of a console variable.
+ *
+ * @param convar Handle to the convar.
+ * @return The boolean value of the convar.
+ * @error Invalid or corrupt Handle.
+ */
+native bool:GetConVarBool(Handle:convar);
+
+/**
+ * Sets the boolean value of a console variable.
+ *
+ * Note: The replicate and notify params are only relevant for the original, Dark Messiah, and
+ * Episode 1 engines. Newer engines automatically do these things when the convar value is changed.
+ *
+ * @param convar Handle to the convar.
+ * @param value New boolean value.
+ * @param replicate If set to true, the new convar value will be set on all clients.
+ * This will only work if the convar has the FCVAR_REPLICATED flag
+ * and actually exists on clients.
+ * @param notify If set to true, clients will be notified that the convar has changed.
+ * This will only work if the convar has the FCVAR_NOTIFY flag.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native SetConVarBool(Handle:convar, bool:value, bool:replicate=false, bool:notify=false);
+
+/**
+ * Returns the integer value of a console variable.
+ *
+ * @param convar Handle to the convar.
+ * @return The integer value of the convar.
+ * @error Invalid or corrupt Handle.
+ */
+native GetConVarInt(Handle:convar);
+
+/**
+ * Sets the integer value of a console variable.
+ *
+ * Note: The replicate and notify params are only relevant for the original, Dark Messiah, and
+ * Episode 1 engines. Newer engines automatically do these things when the convar value is changed.
+ *
+ * @param convar Handle to the convar.
+ * @param value New integer value.
+ * @param replicate If set to true, the new convar value will be set on all clients.
+ * This will only work if the convar has the FCVAR_REPLICATED flag
+ * and actually exists on clients.
+ * @param notify If set to true, clients will be notified that the convar has changed.
+ * This will only work if the convar has the FCVAR_NOTIFY flag.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native SetConVarInt(Handle:convar, value, bool:replicate=false, bool:notify=false);
+
+/**
+ * Returns the floating point value of a console variable.
+ *
+ * @param convar Handle to the convar.
+ * @return The floating point value of the convar.
+ * @error Invalid or corrupt Handle.
+ */
+native Float:GetConVarFloat(Handle:convar);
+
+/**
+ * Sets the floating point value of a console variable.
+ *
+ * Note: The replicate and notify params are only relevant for the original, Dark Messiah, and
+ * Episode 1 engines. Newer engines automatically do these things when the convar value is changed.
+ *
+ * @param convar Handle to the convar.
+ * @param value New floating point value.
+ * @param replicate If set to true, the new convar value will be set on all clients.
+ * This will only work if the convar has the FCVAR_REPLICATED flag
+ * and actually exists on clients.
+ * @param notify If set to true, clients will be notified that the convar has changed.
+ * This will only work if the convar has the FCVAR_NOTIFY flag.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native SetConVarFloat(Handle:convar, Float:value, bool:replicate=false, bool:notify=false);
+
+/**
+ * Retrieves the string value of a console variable.
+ *
+ * @param convar Handle to the convar.
+ * @param value Buffer to store the value of the convar.
+ * @param maxlength Maximum length of string buffer.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native GetConVarString(Handle:convar, String:value[], maxlength);
+
+/**
+ * Sets the string value of a console variable.
+ *
+ * Note: The replicate and notify params are only relevant for the original, Dark Messiah, and
+ * Episode 1 engines. Newer engines automatically do these things when the convar value is changed.
+ *
+ * @param convar Handle to the convar.
+ * @param value New string value.
+ * @param replicate If set to true, the new convar value will be set on all clients.
+ * This will only work if the convar has the FCVAR_REPLICATED flag
+ * and actually exists on clients.
+ * @param notify If set to true, clients will be notified that the convar has changed.
+ * This will only work if the convar has the FCVAR_NOTIFY flag.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native SetConVarString(Handle:convar, const String:value[], bool:replicate=false, bool:notify=false);
+
+/**
+ * Resets the console variable to its default value.
+ *
+ * Note: The replicate and notify params are only relevant for the original, Dark Messiah, and
+ * Episode 1 engines. Newer engines automatically do these things when the convar value is changed.
+ *
+ * @param convar Handle to the convar.
+ * @param replicate If set to true, the new convar value will be set on all clients.
+ * This will only work if the convar has the FCVAR_REPLICATED flag
+ * and actually exists on clients.
+ * @param notify If set to true, clients will be notified that the convar has changed.
+ * This will only work if the convar has the FCVAR_NOTIFY flag.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native ResetConVar(Handle:convar, bool:replicate=false, bool:notify=false);
+
+/**
+ * Retrieves the default string value of a console variable.
+ *
+ * @param convar Handle to the convar.
+ * @param value Buffer to store the default value of the convar.
+ * @param maxlength Maximum length of string buffer.
+ * @return Number of bytes written to the buffer (UTF-8 safe).
+ * @error Invalid or corrupt Handle.
+ */
+native GetConVarDefault(Handle:convar, String:value[], maxlength);
+
+/**
+ * Returns the bitstring of flags on a console variable.
+ *
+ * @param convar Handle to the convar.
+ * @return A bitstring containing the FCVAR_* flags that are enabled.
+ * @error Invalid or corrupt Handle.
+ */
+native GetConVarFlags(Handle:convar);
+
+/**
+ * Sets the bitstring of flags on a console variable.
+ *
+ * @param convar Handle to the convar.
+ * @param flags A bitstring containing the FCVAR_* flags to enable.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native SetConVarFlags(Handle:convar, flags);
+
+/**
+ * Retrieves the specified bound of a console variable.
+ *
+ * @param convar Handle to the convar.
+ * @param type Type of bound to retrieve, ConVarBound_Lower or ConVarBound_Upper.
+ * @param value By-reference cell to store the specified floating point bound value.
+ * @return True if the convar has the specified bound set, false otherwise.
+ * @error Invalid or corrupt Handle.
+ */
+native bool:GetConVarBounds(Handle:convar, ConVarBounds:type, &Float:value);
+
+/**
+ * Sets the specified bound of a console variable.
+ *
+ * @param convar Handle to the convar.
+ * @param type Type of bound to set, ConVarBound_Lower or ConVarBound_Upper
+ * @param set If set to true, convar will use specified bound. If false, bound will be removed.
+ * @param value Floating point value to use as the specified bound.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native SetConVarBounds(Handle:convar, ConVarBounds:type, bool:set, Float:value=0.0);
+
+/**
+ * Retrieves the name of a console variable.
+ *
+ * @param convar Handle to the convar.
+ * @param name Buffer to store the name of the convar.
+ * @param maxlength Maximum length of string buffer.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native GetConVarName(Handle:convar, String:name[], maxlength);
+
+funcenum ConVarQueryFinished
+{
+ /**
+ * Called when a query to retrieve a client's console variable has finished.
+ *
+ * @param cookie Unique identifier of query.
+ * @param client Player index.
+ * @param result Result of query that tells one whether or not query was successful.
+ * See ConVarQueryResult enum for more details.
+ * @param convarName Name of client convar that was queried.
+ * @param convarValue Value of client convar that was queried if successful. This will be "" if it was not.
+ * @param value Value that was passed when query was started.
+ * @noreturn
+ */
+ public(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[], any:value),
+
+ /**
+ * Called when a query to retrieve a client's console variable has finished.
+ *
+ * @param cookie Unique identifier of query.
+ * @param client Player index.
+ * @param result Result of query that tells one whether or not query was successful.
+ * See ConVarQueryResult enum for more details.
+ * @param convarName Name of client convar that was queried.
+ * @param convarValue Value of client convar that was queried if successful. This will be "" if it was not.
+ * @noreturn
+ */
+ public(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[])
+};
+
+/**
+ * Starts a query to retrieve the value of a client's console variable.
+ *
+ * @param client Player index.
+ * @param cvarName Name of client convar to query.
+ * @param callback A function to use as a callback when the query has finished.
+ * @param value Optional value to pass to the callback function.
+ * @return A cookie that uniquely identifies the query.
+ * Returns QUERYCOOKIE_FAILED on failure, such as when used on a bot.
+ */
+native QueryCookie:QueryClientConVar(client, const String:cvarName[], ConVarQueryFinished:callback, any:value=0);
+
+/**
+ * Gets a command iterator. Must be freed with CloseHandle().
+ *
+ * @return A new command iterator.
+ */
+native Handle:GetCommandIterator();
+
+/**
+ * Reads a command iterator, then advances to the next command if any.
+ * Only SourceMod specific commands are returned.
+ *
+ * @param iter Command iterator Handle.
+ * @param name Name buffer.
+ * @param nameLen Name buffer size.
+ * @param eflags Effective default flags of a command.
+ * @param desc Command description buffer.
+ * @param descLen Command description buffer size.
+ * @return True on success, false if there are no more commands.
+ */
+native bool:ReadCommandIterator(Handle:iter,
+ String:name[],
+ nameLen,
+ &eflags=0,
+ String:desc[]="",
+ descLen=0);
+
+/**
+ * Returns whether a client has access to a given command string. The string
+ * can be any override string, as overrides can be independent of
+ * commands. This feature essentially allows you to create custom
+ * flags using the override system.
+ *
+ * @param client Client index.
+ * @param command Command name. If the command is not found, the default
+ * flags are used.
+ * @param flags Flag string to use as a default, if the command or override
+ * is not found.
+ * @param override_only If true, SourceMod will not attempt to find a matching
+ * command, and it will only use the default flags specified.
+ * Otherwise, SourceMod will ignore the default flags if
+ * there is a matching admin command.
+ * @return True if the client has access, false otherwise.
+ */
+native bool:CheckCommandAccess(client,
+ const String:command[],
+ flags,
+ bool:override_only=false);
+
+/**
+ * Returns whether an admin has access to a given command string. The string
+ * can be any override string, as overrides can be independent of
+ * commands. This feature essentially allows you to create custom flags
+ * using the override system.
+ *
+ * @param id AdminId of the admin.
+ * @param command Command name. If the command is not found, the default
+ * flags are used.
+ * @param flags Flag string to use as a default, if the command or override
+ * is not found.
+ * @param override_only If true, SourceMod will not attempt to find a matching
+ * command, and it will only use the default flags specified.
+ * Otherwise, SourceMod will ignore the default flags if
+ * there is a matching admin command.
+ * @return True if the admin has access, false otherwise.
+ */
+native bool:CheckAccess(AdminId:id,
+ const String:command[],
+ flags,
+ bool:override_only=false);
+
+/**
+ * Returns true if the supplied character is valid in a ConVar name.
+ *
+ * @param c Character to validate.
+ * @return True is valid for ConVars, false otherwise
+ */
+stock bool:IsValidConVarChar(c)
+{
+ return (c == '_' || IsCharAlpha(c) || IsCharNumeric(c));
+}
+
+/**
+ * Returns the bitstring of flags of a command.
+ *
+ * @param name Name of the command.
+ * @return A bitstring containing the FCVAR_* flags that are enabled
+ * or INVALID_FCVAR_FLAGS if command not found.
+ */
+native GetCommandFlags(const String:name[]);
+
+/**
+ * Sets the bitstring of flags of a command.
+ *
+ * @param name Name of the command.
+ * @param flags A bitstring containing the FCVAR_* flags to enable.
+ * @return True on success, otherwise false.
+ */
+native bool:SetCommandFlags(const String:name[], flags);
+
+/**
+ * Starts a ConCommandBase search, traversing the list of ConVars and
+ * ConCommands. If a Handle is returned, the next entry must be read
+ * via FindNextConCommand(). The order of the list is undefined.
+ *
+ * @param buffer Buffer to store entry name.
+ * @param max_size Maximum size of the buffer.
+ * @param isCommand Variable to store whether the entry is a command.
+ * If it is not a command, it is a ConVar.
+ * @param flags Variable to store entry flags.
+ * @param description Buffer to store the description, empty if no description present.
+ * @param descrmax_size Maximum size of the description buffer.
+ * @return On success, a ConCmdIter Handle is returned, which
+ * can be read via FindNextConCommand(), and must be
+ * closed via CloseHandle(). Additionally, the output
+ * parameters will be filled with information of the
+ * first ConCommandBase entry.
+ * On failure, INVALID_HANDLE is returned, and the
+ * contents of outputs is undefined.
+ */
+native Handle:FindFirstConCommand(String:buffer[], max_size, &bool:isCommand, &flags=0, String:description[]="", descrmax_size=0);
+
+/**
+ * Reads the next entry in a ConCommandBase iterator.
+ *
+ * @param search ConCmdIter Handle to search.
+ * @param buffer Buffer to store entry name.
+ * @param max_size Maximum size of the buffer.
+ * @param isCommand Variable to store whether the entry is a command.
+ * If it is not a command, it is a ConVar.
+ * @param flags Variable to store entry flags.
+ * @param description Buffer to store the description, empty if no description present.
+ * @param descrmax_size Maximum size of the description buffer.
+ * @return On success, the outputs are filled, the iterator is
+ * advanced to the next entry, and true is returned.
+ * If no more entries exist, false is returned, and the
+ * contents of outputs is undefined.
+ */
+native bool:FindNextConCommand(Handle:search, String:buffer[], max_size, &bool:isCommand, &flags=0, String:description[]="", descrmax_size=0);
+
+/**
+ * Replicates a convar value to a specific client. This does not change the actual convar value.
+ *
+ * @param client Client index
+ * @param convar ConVar handle
+ * @param value String value to send
+ * @return True on success, false on failure
+ * @error Invalid client index, client not in game, or client is fake
+ */
+native bool:SendConVarValue(client, Handle:convar, const String:value[]);
+
+/**
+ * Adds an informational string to the server's public "tags".
+ * This string should be a short, unique identifier.
+ *
+ * Note: Tags are automatically removed when a plugin unloads.
+ * Note: Currently, this function does nothing because of bugs in the Valve master.
+ *
+ * @param tag Tag string to append.
+ * @noreturn
+ */
+native AddServerTag(const String:tag[]);
+
+/**
+ * Removes a tag previously added by the calling plugin.
+ *
+ * @param tag Tag string to remove.
+ * @noreturn
+ */
+native RemoveServerTag(const String:tag[]);
+
+/**
+ * Callback for command listeners. This is invoked whenever any command
+ * reaches the server, from the server console itself or a player.
+ *
+ * Clients may be in the process of connecting when they are executing commands
+ * IsClientConnected(client) is not guaranteed to return true. Other functions
+ * such as GetClientIP() may not work at this point either.
+ *
+ * Returning Plugin_Handled or Plugin_Stop will prevent the original,
+ * baseline code from running.
+ *
+ * -- TEXT BELOW IS IMPLEMENTATION, AND NOT GUARANTEED --
+ * Even if returning Plugin_Handled or Plugin_Stop, some callbacks will still
+ * trigger. These are:
+ * * C++ command dispatch hooks from Metamod:Source plugins
+ * * Reg*Cmd() hooks that did not create new commands.
+ *
+ * @param client Client, or 0 for server.
+ * Client may not be connected or in game.
+ * @param command Command name, lower case. To get name as typed, use
+ * GetCmdArg() and specify argument 0.
+ * @param argc Argument count.
+ * @return Action to take (see extended notes above).
+ */
+functag public Action:CommandListener(client, const String:command[], argc);
+
+#define FEATURECAP_COMMANDLISTENER "command listener"
+
+/**
+ * Adds a callback that will fire when a command is sent to the server.
+ *
+ * Registering commands is designed to create a new command as part of the UI,
+ * whereas this is a lightweight hook on a command string, existing or not.
+ * Using Reg*Cmd to intercept is in poor practice, as it physically creates a
+ * new command and can slow down dispatch in general.
+ *
+ * To see if this feature is available, use FeatureType_Capability and
+ * FEATURECAP_COMMANDLISTENER.
+ *
+ * @param callback Callback.
+ * @param command Command, or if not specified, a global listener.
+ * The command is case insensitive.
+ * @return True if this feature is available on the current game,
+ * false otherwise.
+ */
+native bool:AddCommandListener(CommandListener:callback, const String:command[]="");
+
+/**
+ * Removes a previously added command listener, in reverse order of being added.
+ *
+ * @param callback Callback.
+ * @param command Command, or if not specified, a global listener.
+ * The command is case insensitive.
+ * @error Callback has no active listeners.
+ */
+native RemoveCommandListener(CommandListener:callback, const String:command[]="");
+
+/**
+ * Returns true if the supplied command exists.
+ *
+ * @param command Command to find.
+ * @return True if command is found, false otherwise.
+ */
+stock bool:CommandExists(const String:command[])
+{
+ return (GetCommandFlags(command) != INVALID_FCVAR_FLAGS);
+}
+/**
+ * Global listener for the chat commands.
+ *
+ * @param client Client index.
+ * @param command Command name.
+ * @param sArgs Chat argument string.
+ *
+ * @return An Action value. Returning Plugin_Handled bypasses the game function call.
+ Returning Plugin_Stop bypasses the post hook as well as the game function.
+ */
+forward Action:OnClientSayCommand(client, const String:command[], const String:sArgs[]);
+
+/**
+ * Global post listener for the chat commands.
+ *
+ * @param client Client index.
+ * @param command Command name.
+ * @param sArgs Chat argument string.
+ *
+ */
+forward OnClientSayCommand_Post(client, const String:command[], const String:sArgs[]);
diff --git a/sourcemod-1.5-dev/scripting/include/core.inc b/sourcemod-1.5-dev/scripting/include/core.inc
new file mode 100644
index 0000000..262e186
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/core.inc
@@ -0,0 +1,237 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _core_included
+ #endinput
+#endif
+#define _core_included
+
+#include <version>
+
+/** If this gets changed, you need to update Core's check. */
+#define SOURCEMOD_PLUGINAPI_VERSION 5
+
+struct PlVers
+{
+ version,
+ String:filevers[],
+ String:date[],
+ String:time[]
+};
+
+/**
+ * Function helper values.
+ */
+enum Function
+{
+ INVALID_FUNCTION = -1,
+};
+
+/**
+ * Specifies what to do after a hook completes.
+ */
+enum Action
+{
+ Plugin_Continue = 0, /**< Continue with the original action */
+ Plugin_Changed = 1, /**< Inputs or outputs have been overridden with new values */
+ Plugin_Handled = 3, /**< Handle the action at the end (don't call it) */
+ Plugin_Stop = 4, /**< Immediately stop the hook chain and handle the original */
+};
+
+/**
+ * Specifies identity types.
+ */
+enum Identity
+{
+ Identity_Core = 0,
+ Identity_Extension = 1,
+ Identity_Plugin = 2
+};
+
+public PlVers:__version =
+{
+ version = SOURCEMOD_PLUGINAPI_VERSION,
+ filevers = SOURCEMOD_VERSION,
+ date = __DATE__,
+ time = __TIME__
+};
+
+/**
+ * Plugin status values.
+ */
+enum PluginStatus
+{
+ Plugin_Running=0, /**< Plugin is running */
+ /* All states below are "temporarily" unexecutable */
+ Plugin_Paused, /**< Plugin is loaded but paused */
+ Plugin_Error, /**< Plugin is loaded but errored/locked */
+ /* All states below do not have all natives */
+ Plugin_Loaded, /**< Plugin has passed loading and can be finalized */
+ Plugin_Failed, /**< Plugin has a fatal failure */
+ Plugin_Created, /**< Plugin is created but not initialized */
+ Plugin_Uncompiled, /**< Plugin is not yet compiled by the JIT */
+ Plugin_BadLoad, /**< Plugin failed to load */
+};
+
+/**
+ * Plugin information properties.
+ */
+enum PluginInfo
+{
+ PlInfo_Name, /**< Plugin name */
+ PlInfo_Author, /**< Plugin author */
+ PlInfo_Description, /**< Plugin description */
+ PlInfo_Version, /**< Plugin verison */
+ PlInfo_URL, /**< Plugin URL */
+};
+
+/**
+ * Defines how an extension must expose itself for autoloading.
+ */
+struct Extension
+{
+ const String:name[], /**< Short name */
+ const String:file[], /**< Default file name */
+ bool:autoload, /**< Whether or not to auto-load */
+ bool:required, /**< Whether or not to require */
+};
+
+/**
+ * Defines how a plugin must expose itself for native requiring.
+ */
+struct SharedPlugin
+{
+ const String:name[], /**< Short name */
+ const String:file[], /**< File name */
+ bool:required, /**< Whether or not to require */
+};
+
+public Float:NULL_VECTOR[3]; /**< Pass this into certain functions to act as a C++ NULL */
+public const String:NULL_STRING[1]; /**< pass this into certain functions to act as a C++ NULL */
+
+/**
+ * Horrible compatibility shim.
+ */
+public Extension:__ext_core =
+{
+ name = "Core",
+ file = "core",
+ autoload = 0,
+ required = 0,
+};
+
+native VerifyCoreVersion();
+
+/**
+ * Sets a native as optional, such that if it is unloaded, removed,
+ * or otherwise non-existent, the plugin will still work. Calling
+ * removed natives results in a run-time error.
+ *
+ * @param name Native name.
+ * @noreturn
+ */
+native MarkNativeAsOptional(const String:name[]);
+
+public __ext_core_SetNTVOptional()
+{
+ MarkNativeAsOptional("GetFeatureStatus");
+ MarkNativeAsOptional("RequireFeature");
+ MarkNativeAsOptional("AddCommandListener");
+ MarkNativeAsOptional("RemoveCommandListener");
+
+ MarkNativeAsOptional("BfWriteBool");
+ MarkNativeAsOptional("BfWriteByte");
+ MarkNativeAsOptional("BfWriteChar");
+ MarkNativeAsOptional("BfWriteShort");
+ MarkNativeAsOptional("BfWriteWord");
+ MarkNativeAsOptional("BfWriteNum");
+ MarkNativeAsOptional("BfWriteFloat");
+ MarkNativeAsOptional("BfWriteString");
+ MarkNativeAsOptional("BfWriteEntity");
+ MarkNativeAsOptional("BfWriteAngle");
+ MarkNativeAsOptional("BfWriteCoord");
+ MarkNativeAsOptional("BfWriteVecCoord");
+ MarkNativeAsOptional("BfWriteVecNormal");
+ MarkNativeAsOptional("BfWriteAngles");
+ MarkNativeAsOptional("BfReadBool");
+ MarkNativeAsOptional("BfReadByte");
+ MarkNativeAsOptional("BfReadChar");
+ MarkNativeAsOptional("BfReadShort");
+ MarkNativeAsOptional("BfReadWord");
+ MarkNativeAsOptional("BfReadNum");
+ MarkNativeAsOptional("BfReadFloat");
+ MarkNativeAsOptional("BfReadString");
+ MarkNativeAsOptional("BfReadEntity");
+ MarkNativeAsOptional("BfReadAngle");
+ MarkNativeAsOptional("BfReadCoord");
+ MarkNativeAsOptional("BfReadVecCoord");
+ MarkNativeAsOptional("BfReadVecNormal");
+ MarkNativeAsOptional("BfReadAngles");
+ MarkNativeAsOptional("BfGetNumBytesLeft");
+
+ MarkNativeAsOptional("PbReadInt");
+ MarkNativeAsOptional("PbReadFloat");
+ MarkNativeAsOptional("PbReadBool");
+ MarkNativeAsOptional("PbReadString");
+ MarkNativeAsOptional("PbReadColor");
+ MarkNativeAsOptional("PbReadAngle");
+ MarkNativeAsOptional("PbReadVector");
+ MarkNativeAsOptional("PbReadVector2D");
+ MarkNativeAsOptional("PbGetRepeatedFieldCount");
+ MarkNativeAsOptional("PbSetInt");
+ MarkNativeAsOptional("PbSetFloat");
+ MarkNativeAsOptional("PbSetBool");
+ MarkNativeAsOptional("PbSetString");
+ MarkNativeAsOptional("PbSetColor");
+ MarkNativeAsOptional("PbSetAngle");
+ MarkNativeAsOptional("PbSetVector");
+ MarkNativeAsOptional("PbSetVector2D");
+ MarkNativeAsOptional("PbAddInt");
+ MarkNativeAsOptional("PbAddFloat");
+ MarkNativeAsOptional("PbAddBool");
+ MarkNativeAsOptional("PbAddString");
+ MarkNativeAsOptional("PbAddColor");
+ MarkNativeAsOptional("PbAddAngle");
+ MarkNativeAsOptional("PbAddVector");
+ MarkNativeAsOptional("PbAddVector2D");
+ MarkNativeAsOptional("PbRemoveRepeatedFieldValue");
+ MarkNativeAsOptional("PbReadMessage");
+ MarkNativeAsOptional("PbReadRepeatedMessage");
+ MarkNativeAsOptional("PbAddMessage");
+
+ VerifyCoreVersion();
+}
+
+
+#define AUTOLOAD_EXTENSIONS
+#define REQUIRE_EXTENSIONS
+#define REQUIRE_PLUGIN
diff --git a/sourcemod-1.5-dev/scripting/include/cstrike.inc b/sourcemod-1.5-dev/scripting/include/cstrike.inc
new file mode 100644
index 0000000..45ccac0
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/cstrike.inc
@@ -0,0 +1,422 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _cstrike_included
+ #endinput
+#endif
+#define _cstrike_included
+
+#define CS_TEAM_NONE 0 /**< No team yet. */
+#define CS_TEAM_SPECTATOR 1 /**< Spectators. */
+#define CS_TEAM_T 2 /**< Terrorists. */
+#define CS_TEAM_CT 3 /**< Counter-Terrorists. */
+
+#define CS_SLOT_PRIMARY 0 /**< Primary weapon slot. */
+#define CS_SLOT_SECONDARY 1 /**< Secondary weapon slot. */
+#define CS_SLOT_KNIFE 2 /**< Knife slot. */
+#define CS_SLOT_GRENADE 3 /**< Grenade slot (will only return one grenade). */
+#define CS_SLOT_C4 4 /**< C4 slot. */
+
+#define CS_DMG_HEADSHOT (1 << 30) /**< Headshot */
+
+enum CSRoundEndReason
+{
+ CSRoundEnd_TargetBombed = 0, /**< Target Successfully Bombed! */
+ CSRoundEnd_VIPEscaped, /**< The VIP has escaped! */
+ CSRoundEnd_VIPKilled, /**< VIP has been assassinated! */
+ CSRoundEnd_TerroristsEscaped, /**< The terrorists have escaped! */
+ CSRoundEnd_CTStoppedEscape, /**< The CTs have prevented most of the terrorists from escaping! */
+ CSRoundEnd_TerroristsStopped, /**< Escaping terrorists have all been neutralized! */
+ CSRoundEnd_BombDefused, /**< The bomb has been defused! */
+ CSRoundEnd_CTWin, /**< Counter-Terrorists Win! */
+ CSRoundEnd_TerroristWin, /**< Terrorists Win! */
+ CSRoundEnd_Draw, /**< Round Draw! */
+ CSRoundEnd_HostagesRescued, /**< All Hostages have been rescued! */
+ CSRoundEnd_TargetSaved, /**< Target has been saved! */
+ CSRoundEnd_HostagesNotRescued, /**< Hostages have not been rescued! */
+ CSRoundEnd_TerroristsNotEscaped, /**< Terrorists have not escaped! */
+ CSRoundEnd_VIPNotEscaped, /**< VIP has not escaped! */
+ CSRoundEnd_GameStart, /**< Game Commencing! */
+
+ // The below only exist on CS:GO
+ CSRoundEnd_TerroristsSurrender, /**< Terrorists Surrender */
+ CSRoundEnd_CTSurrender, /**< CTs Surrender */
+};
+
+enum CSWeaponID
+{
+ CSWeapon_NONE = 0,
+ CSWeapon_P228,
+ CSWeapon_GLOCK,
+ CSWeapon_SCOUT,
+ CSWeapon_HEGRENADE,
+ CSWeapon_XM1014,
+ CSWeapon_C4,
+ CSWeapon_MAC10,
+ CSWeapon_AUG,
+ CSWeapon_SMOKEGRENADE,
+ CSWeapon_ELITE,
+ CSWeapon_FIVESEVEN,
+ CSWeapon_UMP45,
+ CSWeapon_SG550,
+ CSWeapon_GALIL,
+ CSWeapon_FAMAS,
+ CSWeapon_USP,
+ CSWeapon_AWP,
+ CSWeapon_MP5NAVY,
+ CSWeapon_M249,
+ CSWeapon_M3,
+ CSWeapon_M4A1,
+ CSWeapon_TMP,
+ CSWeapon_G3SG1,
+ CSWeapon_FLASHBANG,
+ CSWeapon_DEAGLE,
+ CSWeapon_SG552,
+ CSWeapon_AK47,
+ CSWeapon_KNIFE,
+ CSWeapon_P90,
+ CSWeapon_SHIELD,
+ CSWeapon_KEVLAR,
+ CSWeapon_ASSAULTSUIT,
+ CSWeapon_NIGHTVISION,
+ CSWeapon_GALILAR,
+ CSWeapon_BIZON,
+ CSWeapon_MAG7,
+ CSWeapon_NEGEV,
+ CSWeapon_SAWEDOFF,
+ CSWeapon_TEC9,
+ CSWeapon_TASER,
+ CSWeapon_HKP2000,
+ CSWeapon_MP7,
+ CSWeapon_MP9,
+ CSWeapon_NOVA,
+ CSWeapon_P250,
+ CSWeapon_SCAR17,
+ CSWeapon_SCAR20,
+ CSWeapon_SG556,
+ CSWeapon_SSG08,
+ CSWeapon_KNIFE_GG,
+ CSWeapon_MOLOTOV,
+ CSWeapon_DECOY,
+ CSWeapon_INCGRENADE,
+ CSWeapon_DEFUSER
+};
+
+/**
+ * Called when a player attempts to purchase an item.
+ * Return Plugin_Continue to allow the purchase or return a
+ * higher action to deny.
+ *
+ * @param client Client index
+ * @param weapon User input for weapon name
+ */
+forward Action:CS_OnBuyCommand(client, const String:weapon[]);
+
+/**
+ * Called when CSWeaponDrop is called
+ * Return Plugin_Continue to allow the call or return a
+ * higher action to deny.
+ *
+ * @param client Client index
+ * @param weaponIndex Weapon index
+ */
+forward Action:CS_OnCSWeaponDrop(client, weaponIndex);
+
+/**
+ * Called when game retrieves a weapon's price for a player.
+ * Return Plugin_Continue to use default value or return a higher
+ * action to use a newly-set price.
+ *
+ * @note This can be called multiple times per weapon purchase
+ *
+ * @param client Client index
+ * @param weapon Weapon classname
+ * @param price Buffer param for the price of the weapon
+ *
+ * @note Not all "weapons" call GetWeaponPrice. Example: c4, knife, vest, vest helmet, night vision.
+ */
+forward Action:CS_OnGetWeaponPrice(client, const String:weapon[], &price);
+
+/**
+ * Called when TerminateRound is called.
+ * Return Plugin_Continue to ignore, return Plugin_Changed to continue,
+ * using the given delay and reason, or return Plugin_Handled or a higher
+ * action to block TerminateRound from firing.
+ *
+ * @param delay Time (in seconds) until new round starts
+ * @param reason Reason for round end
+ */
+forward Action:CS_OnTerminateRound(&Float:delay, &CSRoundEndReason:reason);
+
+/**
+ * Respawns a player.
+ *
+ * @param client Player's index.
+ * @noreturn
+ * @error Invalid client index, client not in game.
+ */
+native CS_RespawnPlayer(client);
+
+/**
+ * Switches the player's team.
+ *
+ * @param client Player's index.
+ * @param team Team index.
+ * @noreturn
+ * @error Invalid client index, client not in game.
+ */
+native CS_SwitchTeam(client, team);
+
+/**
+ * Forces a player to drop or toss their weapon
+ *
+ * @param client Player's index.
+ * @param weaponIndex Index of weapon to drop.
+ * @param toss True to toss weapon (with velocity) or false to just drop weapon
+ * @param blockhook Set to true to stop the corresponding CS_OnCSWeaponDrop
+ *
+ * @noreturn
+ * @error Invalid client index, client not in game, or invalid weapon index.
+ */
+native CS_DropWeapon(client, weaponIndex, bool:toss, bool:blockhook = false);
+
+/**
+ * Forces round to end with a reason
+ *
+ * @param delay Time (in seconds) to delay before new round starts
+ * @param reason Reason for the round ending
+ * @param blockhook Set to true to stop the corresponding CS_OnTerminateRound
+ * forward from being called.
+ * @noreturn
+ */
+native CS_TerminateRound(Float:delay, CSRoundEndReason:reason, bool:blockhook = false);
+
+/**
+ * Gets a weapon name from a weapon alias
+ *
+ * @param alias Weapons alias to get weapon name for.
+ * @param weapon Buffer to store weapons name
+ * @param size Size of buffer to store the weapons name.
+ * @noreturn
+ *
+ * @note Will set the buffer to the original alias if it is not an alias to a weapon.
+ */
+native CS_GetTranslatedWeaponAlias(const String:alias[], String:weapon[], size);
+
+/**
+ * Gets a weapon's price
+ *
+ * @param client Client to check weapon price for.
+ * @param id Weapon id for the weapon to check
+ * @param defaultprice Set to true to get defaultprice.
+ * @return Returns price of the weapon (even if modified)
+ *
+ * @error Invalid client, failing to get weapon info, or failing to get price offset.
+ * @note c4, knife and shield will always return 0. vest, vest helmet and night vision will always return default price.
+ */
+native CS_GetWeaponPrice(client, CSWeaponID:id, bool:defaultprice = false);
+
+/**
+ * Gets a clients clan tag
+ * @param client Client index to get clan tag for.
+ * @param buffer Buffer to store clients clan tag in.
+ * @param size Size of the buffer.
+ * @return Number of non-null bytes written.
+ *
+ * @error Invalid client.
+ */
+native CS_GetClientClanTag(client, String:buffer[], size);
+
+/**
+ * Sets a clients clan tag
+ * @param client Client index to set clan tag for.
+ * @param tag Tag to set clients clan tag as.
+ * @noreturn
+ *
+ * @error Invalid client.
+ */
+native CS_SetClientClanTag(client, const String:tag[]);
+
+/**
+ * Gets a team's score
+ * @param team Team index to get score for.
+ * @return Returns the internal team score.
+ *
+ * @error Invalid team index.
+ */
+native CS_GetTeamScore(team);
+
+/**
+ * Sets a team's score
+ * @param team Team index to set score for.
+ * @param value Value to set teams score as.
+ * @noreturn
+ *
+ * @error Invalid team index.
+ * @note This will update the scoreboard only after the scoreboard update function is called. Use SetTeamScore plus this to update the scoreboard instantly and save values correctly.
+ */
+native CS_SetTeamScore(team, value);
+
+/**
+ * Gets a client's mvp count
+ * @param client Client index to get mvp count of.
+ * @return Returns the client's internal MVP count.
+ *
+ * @error Invalid client.
+ */
+native CS_GetMVPCount(client);
+
+/**
+ * Sets a client's mvp count
+ * @param client Client index to set mvp count for.
+ * @param value Value to set client's mvp count as.
+ * @noreturn
+ *
+ * @error Invalid client.
+ */
+native CS_SetMVPCount(client, value);
+
+/**
+ * Gets a client's contribution score (CS:GO only)
+ * @param client Client index to get score of.
+ * @return Returns the client's score.
+ *
+ * @error Invalid client.
+ */
+native CS_GetClientContributionScore(client);
+
+/**
+ * Sets a client's contribution score (CS:GO only)
+ * @param client Client index to set score for.
+ * @param value Value to set client's score as.
+ * @noreturn
+ *
+ * @error Invalid client.
+ */
+native CS_SetClientContributionScore(client, value);
+
+/**
+ * Gets a client's assists (CS:GO only)
+ * @param client Client index to get assists of.
+ * @return Returns the client's assists.
+ *
+ * @error Invalid client.
+ */
+native CS_GetClientAssists(client);
+
+/**
+ * Sets a client's assists (CS:GO only)
+ * @param client Client index to set assists for.
+ * @param value Value to set client's assists as.
+ * @noreturn
+ *
+ * @error Invalid client.
+ */
+native CS_SetClientAssists(client, value);
+
+/**
+ * Gets a weaponID from a alias
+ * @param alias Weapon alias to attempt to get an id for.
+ * @return Returns a weapon id or 0 if failed to find a match.
+ *
+ * @note For best results use CS_GetTranslatedWeaponAlias on the weapon name before passing it.
+ */
+native CSWeaponID:CS_AliasToWeaponID(const String:alias[]);
+
+/**
+ * Gets a alias from a weaponID
+ * @param weaponID WeaponID to get alias for.
+ * @param destination Destination string to hold the weapon alias.
+ * @param len Length of the destination array.
+ * @return Returns number of cells written.
+ */
+native CS_WeaponIDToAlias(CSWeaponID:weaponID, String:destination[], len);
+
+/**
+ * Returns weather a WeaponID is valid on the current mod (css or csgo)
+ * @param weaponID WeaponID to check
+ * @return Returns true if its a valid WeaponID false otherwise.
+ *
+ * @note This will return false always for CSWeapon_NONE
+ */
+native bool:CS_IsValidWeaponID(CSWeaponID:id);
+
+/**
+ * Sets a player's model based on their current class
+ *
+ * @param client Player's index.
+ * @noreturn
+ * @error Invalid client index, client not in game.
+ */
+native CS_UpdateClientModel(client);
+
+/**
+ * Do not edit below this line!
+ */
+public Extension:__ext_cstrike =
+{
+ name = "cstrike",
+ file = "games/game.cstrike.ext",
+ autoload = 0,
+#if defined REQUIRE_EXTENSIONS
+ required = 1,
+#else
+ required = 0,
+#endif
+};
+
+#if !defined REQUIRE_EXTENSIONS
+public __ext_cstrike_SetNTVOptional()
+{
+ MarkNativeAsOptional("CS_RespawnPlayer");
+ MarkNativeAsOptional("CS_SwitchTeam");
+ MarkNativeAsOptional("CS_DropWeapon");
+ MarkNativeAsOptional("CS_TerminateRound");
+ MarkNativeAsOptional("CS_GetTranslatedWeaponAlias");
+ MarkNativeAsOptional("CS_GetWeaponPrice");
+ MarkNativeAsOptional("CS_GetClientClanTag");
+ MarkNativeAsOptional("CS_SetClientClanTag");
+ MarkNativeAsOptional("CS_GetTeamScore");
+ MarkNativeAsOptional("CS_SetTeamScore");
+ MarkNativeAsOptional("CS_GetMVPCount");
+ MarkNativeAsOptional("CS_SetMVPCount");
+ MarkNativeAsOptional("CS_GetClientContributionScore");
+ MarkNativeAsOptional("CS_SetClientContributionScore");
+ MarkNativeAsOptional("CS_GetClientAssists");
+ MarkNativeAsOptional("CS_SetClientAssists");
+ MarkNativeAsOptional("CS_AliasToWeaponID");
+ MarkNativeAsOptional("CS_WeaponIDToAlias");
+ MarkNativeAsOptional("CS_IsValidWeaponID");
+ MarkNativeAsOptional("CS_UpdateClientModel");
+}
+#endif
+
diff --git a/sourcemod-1.5-dev/scripting/include/datapack.inc b/sourcemod-1.5-dev/scripting/include/datapack.inc
new file mode 100644
index 0000000..ce3d8b7
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/datapack.inc
@@ -0,0 +1,142 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _datapack_included
+ #endinput
+#endif
+#define _datapack_included
+
+/**
+ * Creates a new data pack.
+ *
+ * @return A Handle to the data pack. Must be closed with CloseHandle().
+ */
+native Handle:CreateDataPack();
+
+/**
+ * Packs a normal cell into a data pack.
+ *
+ * @param pack Handle to the data pack.
+ * @param cell Cell to add.
+ * @noreturn
+ * @error Invalid handle.
+ */
+native WritePackCell(Handle:pack, any:cell);
+
+/**
+ * Packs a float into a data pack.
+ *
+ * @param pack Handle to the data pack.
+ * @param val Float to add.
+ * @noreturn
+ * @error Invalid handle.
+ */
+native WritePackFloat(Handle:pack, Float:val);
+
+/**
+ * Packs a string into a data pack.
+ *
+ * @param pack Handle to the data pack.
+ * @param str String to add.
+ * @noreturn
+ * @error Invalid handle.
+ */
+native WritePackString(Handle:pack, const String:str[]);
+
+/**
+ * Reads a cell from a data pack.
+ *
+ * @param pack Handle to the data pack.
+ * @return Cell value.
+ * @error Invalid handle, or bounds error.
+ */
+native any:ReadPackCell(Handle:pack);
+
+/**
+ * Reads a float from a data pack.
+ *
+ * @param pack Handle to the data pack.
+ * @return Float value.
+ * @error Invalid handle, or bounds error.
+ */
+native Float:ReadPackFloat(Handle:pack);
+
+/**
+ * Reads a string from a data pack.
+ *
+ * @param pack Handle to the data pack.
+ * @param buffer Destination string buffer.
+ * @param maxlen Maximum length of output string buffer.
+ * @noreturn
+ * @error Invalid handle, or bounds error.
+ */
+native ReadPackString(Handle:pack, String:buffer[], maxlen);
+
+/**
+ * Resets the position in a data pack.
+ *
+ * @param pack Handle to the data pack.
+ * @param clear If true, clears the contained data.
+ * @noreturn
+ * @error Invalid handle.
+ */
+native ResetPack(Handle:pack, bool:clear=false);
+
+/**
+ * Returns the read or write position in a data pack.
+ *
+ * @param pack Handle to the data pack.
+ * @return Numerical position in the data pack.
+ * @error Invalid handle.
+ */
+native GetPackPosition(Handle:pack);
+
+/**
+ * Sets the read/write position in a data pack.
+ *
+ * @param pack Handle to the data pack.
+ * @param position New position to set.
+ * @noreturn
+ * @error Invalid handle, or position is beyond the pack bounds.
+ */
+native SetPackPosition(Handle:pack, position);
+
+/**
+ * Returns whether or not a specified number of bytes from the data pack
+ * position to the end can be read.
+ *
+ * @param pack Handle to the data pack.
+ * @param bytes Number of bytes to simulate reading.
+ * @return True if can be read, false otherwise.
+ * @error Invalid handle.
+ */
+native bool:IsPackReadable(Handle:pack, bytes);
diff --git a/sourcemod-1.5-dev/scripting/include/dbi.inc b/sourcemod-1.5-dev/scripting/include/dbi.inc
new file mode 100644
index 0000000..bbb1d6e
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/dbi.inc
@@ -0,0 +1,762 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _dbi_included
+ #endinput
+#endif
+#define _dbi_included
+
+/**
+ * @handle Driver
+ *
+ * Contains information about an SQL driver.
+ */
+
+/**
+ * @handle Database
+ *
+ * Contains information about a database connection.
+ */
+
+/**
+ * @handle Query
+ *
+ * Contains information about an active query and its
+ * result sets.
+ */
+
+/**
+ * @handle Statement : Query
+ *
+ * Extends a Query Handle and can be used as a Query Handle.
+ * Statement Handles are for prepared queries and contain
+ * their own function for binding parameters. Statement
+ * Handles can be used instead of database Handles in a few
+ * select functions.
+ */
+
+/**
+ * Describes a database field fetch status.
+ */
+enum DBResult
+{
+ DBVal_Error = 0, /**< Column number/field is invalid. */
+ DBVal_TypeMismatch = 1, /**< You cannot retrieve this data with this type. */
+ DBVal_Null = 2, /**< Field has no data (NULL) */
+ DBVal_Data = 3, /**< Field has data */
+};
+
+/**
+ * Describes binding types.
+ */
+enum DBBindType
+{
+ DBBind_Int = 0, /**< Bind an integer. */
+ DBBind_Float = 1, /**< Bind a float. */
+ DBBind_String = 2, /**< Bind a string. */
+};
+
+/**
+ * Threading priority level.
+ */
+enum DBPriority
+{
+ DBPrio_High = 0, /**< High priority. */
+ DBPrio_Normal = 1, /**< Normal priority. */
+ DBPrio_Low = 2, /**< Low priority. */
+};
+
+/**
+ * Creates an SQL connection from a named configuration.
+ *
+ * @param confname Named configuration.
+ * @param persistent True to re-use a previous persistent connection if
+ * possible, false otherwise.
+ * @param error Error buffer.
+ * @param maxlength Maximum length of the error buffer.
+ * @return A database connection Handle, or INVALID_HANDLE on failure.
+ */
+native Handle:SQL_Connect(const String:confname[], bool:persistent, String:error[], maxlength);
+
+/**
+ * Creates a default SQL connection.
+ *
+ * @param error Error buffer.
+ * @param maxlength Maximum length of the error buffer.
+ * @param persistent True to re-use a previous persistent connection
+ * if possible, false otherwise.
+ * @return A database connection Handle, or INVALID_HANDLE on failure.
+ * On failure the error buffer will be filled with a message.
+ */
+stock Handle:SQL_DefConnect(String:error[], maxlength, bool:persistent=true)
+{
+ return SQL_Connect("default", persistent, error, maxlength);
+}
+
+/**
+ * Connects to a database using key value pairs containing the database info.
+ * The key/value pairs should match what would be in databases.cfg.
+ *
+ * I.e. "driver" should be "default" or a driver name (or ommitted for
+ * the default). For SQLite, only the "database" parameter is needed in addition.
+ * For drivers which require external connections, more of the parameters may be
+ * needed.
+ *
+ * In general it is discouraged to use this function. Connections should go through
+ * databases.cfg for greatest flexibility on behalf of users.
+ *
+ * @param keyvalues Key/value pairs from a KeyValues handle, describing the connection.
+ * @param error Error buffer.
+ * @param maxlength Maximum length of the error buffer.
+ * @param persistent True to re-use a previous persistent connection if
+ * possible, false otherwise.
+ * @return A database connection Handle, or INVALID_HANDLE on failure.
+ * On failure the error buffer will be filled with a message.
+ * @error Invalid KeyValues handle.
+ */
+native Handle:SQL_ConnectCustom(Handle:keyvalues,
+ String:error[],
+ maxlength,
+ bool:persistent);
+
+/**
+ * Grabs a handle to an SQLite database, creating one if it does not exist.
+ *
+ * Unless there are extenuating circumstances, you should consider using "sourcemod-local" as the
+ * database name. This provides some unification between plugins on behalf of users.
+ *
+ * As a precaution, you should always create some sort of unique prefix to your table names so
+ * there are no conflicts, and you should never drop or modify tables that you do not own.
+ *
+ * @param database Database name.
+ * @param error Error buffer.
+ * @param maxlength Maximum length of the error buffer.
+ * @return A database connection Handle, or INVALID_HANDLE on failure.
+ * On failure the error buffer will be filled with a message.
+ */
+stock Handle:SQLite_UseDatabase(const String:database[],
+ String:error[],
+ maxlength)
+{
+ new Handle:kv, Handle:db;
+
+ kv = CreateKeyValues("");
+ KvSetString(kv, "driver", "sqlite");
+ KvSetString(kv, "database", database);
+
+ db = SQL_ConnectCustom(kv, error, maxlength, false);
+
+ CloseHandle(kv);
+
+ return db;
+}
+
+/**
+ * This function is deprecated. Use SQL_ConnectCustom or SQLite_UseDatabase instead.
+ */
+#pragma deprecated Use SQL_ConnectCustom instead.
+native Handle:SQL_ConnectEx(Handle:driver,
+ const String:host[],
+ const String:user[],
+ const String:pass[],
+ const String:database[],
+ String:error[],
+ maxlength,
+ bool:persistent=true,
+ port=0,
+ maxTimeout=0);
+
+/**
+ * Returns if a named configuration is present in databases.cfg.
+ *
+ * @param name Configuration name.
+ * @return True if it exists, false otherwise.
+ */
+native bool:SQL_CheckConfig(const String:name[]);
+
+/**
+ * Returns a driver Handle from a name string.
+ *
+ * If the driver is not found, SourceMod will attempt
+ * to load an extension named dbi.<name>.ext.[dll|so].
+ *
+ * @param name Driver identification string, or an empty
+ * string to return the default driver.
+ * @return Driver Handle, or INVALID_HANDLE on failure.
+ */
+native Handle:SQL_GetDriver(const String:name[]="");
+
+/**
+ * Reads the driver of an opened database.
+ *
+ * @param database Database Handle.
+ * @param ident Option buffer to store the identification string.
+ * @param ident_length Maximum length of the buffer.
+ * @return Driver Handle.
+ */
+native Handle:SQL_ReadDriver(Handle:database, String:ident[]="", ident_length=0);
+
+/**
+ * Retrieves a driver's identification string.
+ *
+ * Example: "mysql", "sqlite"
+ *
+ * @param driver Driver Handle, or INVALID_HANDLE for the default driver.
+ * @param ident Identification string buffer.
+ * @param maxlength Maximum length of the buffer.
+ * @noreturn
+ * @error Invalid Handle other than INVALID_HANDLE.
+ */
+native SQL_GetDriverIdent(Handle:driver, String:ident[], maxlength);
+
+/**
+ * Retrieves a driver's product string.
+ *
+ * Example: "MySQL", "SQLite"
+ *
+ * @param driver Driver Handle, or INVALID_HANDLE for the default driver.
+ * @param product Product string buffer.
+ * @param maxlength Maximum length of the buffer.
+ * @noreturn
+ * @error Invalid Handle other than INVALID_HANDLE.
+ */
+native SQL_GetDriverProduct(Handle:driver, String:product[], maxlength);
+
+/**
+ * Sets the character set of the current connection.
+ * Like SET NAMES .. in mysql, but stays after connection problems.
+ *
+ * Example: "utf8", "latin1"
+ *
+ * @param database Database Handle.
+ * @param characterset The character set string to change to.
+ * @return True, if character set was changed, false otherwise.
+ */
+native bool:SQL_SetCharset(Handle:database, const String:charset[]);
+
+/**
+ * Returns the number of affected rows from the last query.
+ *
+ * @param hndl A database OR statement Handle.
+ * @return Number of rows affected by the last query.
+ * @error Invalid database or statement Handle.
+ */
+native SQL_GetAffectedRows(Handle:hndl);
+
+/**
+ * Returns the last query's insertion id.
+ *
+ * @param hndl A database, query, OR statement Handle.
+ * @return Last query's insertion id.
+ * @error Invalid database, query, or statement Handle.
+ */
+native SQL_GetInsertId(Handle:hndl);
+
+/**
+ * Returns the error reported by the last query.
+ *
+ * @param hndl A database, query, OR statement Handle.
+ * @param error Error buffer.
+ * @param maxlength Maximum length of the buffer.
+ * @return True if there was an error, false otherwise.
+ * @error Invalid database, query, or statement Handle.
+ */
+native bool:SQL_GetError(Handle:hndl, String:error[], maxlength);
+
+/**
+ * Escapes a database string for literal insertion. This is not needed
+ * for binding strings in prepared statements.
+ *
+ * Generally, database strings are inserted into queries enclosed in
+ * single quotes ('). If user input has a single quote in it, the
+ * quote needs to be escaped. This function ensures that any unsafe
+ * characters are safely escaped according to the database engine and
+ * the database's character set.
+ *
+ * NOTE: SourceMod only guarantees properly escaped strings when the query
+ * encloses the string in ''. While drivers tend to allow " instead, the string
+ * may be not be escaped (for example, on SQLite)!
+ *
+ * @param database A database Handle.
+ * @param string String to quote.
+ * @param buffer Buffer to store quoted string in.
+ * @param maxlength Maximum length of the buffer.
+ * @param written Optionally returns the number of bytes written.
+ * @return True on success, false if buffer is not big enough.
+ * The buffer must be at least 2*strlen(string)+1.
+ * @error Invalid database or statement Handle.
+ */
+native bool:SQL_EscapeString(Handle:database,
+ const String:string[],
+ String:buffer[],
+ maxlength,
+ &written=0);
+
+/**
+ * This is a backwards compatibility stock. You should use SQL_EscapeString()
+ * instead, as this function will probably be deprecated in SourceMod 1.1.
+ */
+stock bool:SQL_QuoteString(Handle:database,
+ const String:string[],
+ String:buffer[],
+ maxlength,
+ &written=0)
+{
+ return SQL_EscapeString(database, string, buffer, maxlength, written);
+}
+
+/**
+ * Executes a query and ignores the result set.
+ *
+ * @param database A database Handle.
+ * @param query Query string.
+ * @param len Optional parameter to specify the query length, in
+ * bytes. This can be used to send binary queries that
+ * have a premature terminator.
+ * @return True if query succeeded, false otherwise. Use
+ * SQL_GetError to find the last error.
+ * @error Invalid database Handle.
+ */
+native bool:SQL_FastQuery(Handle:database, const String:query[], len=-1);
+
+/**
+ * Executes a simple query and returns a new query Handle for
+ * receiving the results.
+ *
+ * @param database A database Handle.
+ * @param query Query string.
+ * @param len Optional parameter to specify the query length, in
+ * bytes. This can be used to send binary queries that
+ * have a premature terminator.
+ * @return A new Query Handle on success, INVALID_HANDLE
+ * otherwise. The Handle must be freed with CloseHandle().
+ * @error Invalid database Handle.
+ */
+native Handle:SQL_Query(Handle:database, const String:query[], len=-1);
+
+/**
+ * Creates a new prepared statement query. Prepared statements can
+ * be executed any number of times. They can also have placeholder
+ * parameters, similar to variables, which can be bound safely and
+ * securely (for example, you do not need to quote bound strings).
+ *
+ * Statement handles will work in any function that accepts a Query handle.
+ *
+ * @param database A database Handle.
+ * @param query Query string.
+ * @param error Error buffer.
+ * @param maxlength Maximum size of the error buffer.
+ * @return A new statement Handle on success, INVALID_HANDLE
+ * otherwise. The Handle must be freed with CloseHandle().
+ * @error Invalid database Handle.
+ */
+native Handle:SQL_PrepareQuery(Handle:database, const String:query[], String:error[], maxlength);
+
+/**
+ * Advances to the next set of results.
+ *
+ * In some SQL implementations, multiple result sets can exist on one query.
+ * This is possible in MySQL with simple queries when executing a CALL
+ * query. If this is the case, all result sets must be processed before
+ * another query is made.
+ *
+ * @param query A query Handle.
+ * @return True if there was another result set, false otherwise.
+ * @error Invalid query Handle.
+ */
+native bool:SQL_FetchMoreResults(Handle:query);
+
+/**
+ * Returns whether or not a result set exists. This will
+ * return true even if 0 results were returned, but false
+ * on queries like UPDATE, INSERT, or DELETE.
+ *
+ * @param query A query (or statement) Handle.
+ * @return True if there is a result set, false otherwise.
+ * @error Invalid query Handle.
+ */
+native bool:SQL_HasResultSet(Handle:query);
+
+/**
+ * Retrieves the number of rows in the last result set.
+ *
+ * @param query A query (or statement) Handle.
+ * @return Number of rows in the current result set.
+ * @error Invalid query Handle.
+ */
+native SQL_GetRowCount(Handle:query);
+
+/**
+ * Retrieves the number of fields in the last result set.
+ *
+ * @param query A query (or statement) Handle.
+ * @return Number of fields in the current result set.
+ * @error Invalid query Handle.
+ */
+native SQL_GetFieldCount(Handle:query);
+
+/**
+ * Retrieves the name of a field by index.
+ *
+ * @param query A query (or statement) Handle.
+ * @param field Field number (starting from 0).
+ * @param name Name buffer.
+ * @param maxlength Maximum length of the name buffer.
+ * @noreturn
+ * @error Invalid query Handle, invalid field index, or
+ * no current result set.
+ */
+native SQL_FieldNumToName(Handle:query, field, String:name[], maxlength);
+
+/**
+ * Retrieves a field index by name.
+ *
+ * @param query A query (or statement) Handle.
+ * @param name Name of the field (case sensitive).
+ * @param field Variable to store field index in.
+ * @return True if found, false if not found.
+ * @error Invalid query Handle or no current result set.
+ */
+native bool:SQL_FieldNameToNum(Handle:query, const String:name[], &field);
+
+/**
+ * Fetches a row from the current result set. This must be
+ * successfully called before any results are fetched.
+ *
+ * If this function fails, SQL_MoreResults() can be used to
+ * tell if there was an error or the result set is finished.
+ *
+ * @param query A query (or statement) Handle.
+ * @return True if a row was fetched, false otherwise.
+ * @error Invalid query Handle.
+ */
+native bool:SQL_FetchRow(Handle:query);
+
+/**
+ * Returns if there are more rows.
+ *
+ * @param query A query (or statement) Handle.
+ * @return True if there are more rows, false otherwise.
+ * @error Invalid query Handle.
+ */
+native bool:SQL_MoreRows(Handle:query);
+
+/**
+ * Rewinds a result set back to the first result.
+ *
+ * @param query A query (or statement) Handle.
+ * @return True on success, false otherwise.
+ * @error Invalid query Handle or no current result set.
+ */
+native bool:SQL_Rewind(Handle:query);
+
+/**
+ * Fetches a string from a field in the current row of a result set.
+ * If the result is NULL, an empty string will be returned. A NULL
+ * check can be done with the result parameter, or SQL_IsFieldNull().
+ *
+ * @param query A query (or statement) Handle.
+ * @param field The field index (starting from 0).
+ * @param buffer String buffer.
+ * @param maxlength Maximum size of the string buffer.
+ * @param result Optional variable to store the status of the return value.
+ * @return Number of bytes written.
+ * @error Invalid query Handle or field index, invalid
+ * type conversion requested from the database,
+ * or no current result set.
+ */
+native SQL_FetchString(Handle:query, field, String:buffer[], maxlength, &DBResult:result=DBVal_Error);
+
+/**
+ * Fetches a float from a field in the current row of a result set.
+ * If the result is NULL, a value of 0.0 will be returned. A NULL
+ * check can be done with the result parameter, or SQL_IsFieldNull().
+ *
+ * @param query A query (or statement) Handle.
+ * @param field The field index (starting from 0).
+ * @param result Optional variable to store the status of the return value.
+ * @return A float value.
+ * @error Invalid query Handle or field index, invalid
+ * type conversion requested from the database,
+ * or no current result set.
+ */
+native Float:SQL_FetchFloat(Handle:query, field, &DBResult:result=DBVal_Error);
+
+/**
+ * Fetches an integer from a field in the current row of a result set.
+ * If the result is NULL, a value of 0 will be returned. A NULL
+ * check can be done with the result parameter, or SQL_IsFieldNull().
+ *
+ * @param query A query (or statement) Handle.
+ * @param field The field index (starting from 0).
+ * @param result Optional variable to store the status of the return value.
+ * @return An integer value.
+ * @error Invalid query Handle or field index, invalid
+ * type conversion requested from the database,
+ * or no current result set.
+ */
+native SQL_FetchInt(Handle:query, field, &DBResult:result=DBVal_Error);
+
+/**
+ * Returns whether a field's data in the current row of a result set is
+ * NULL or not. NULL is an SQL type which means "no data."
+ *
+ * @param query A query (or statement) Handle.
+ * @param field The field index (starting from 0).
+ * @return True if data is NULL, false otherwise.
+ * @error Invalid query Handle or field index, or no
+ * current result set.
+ */
+native bool:SQL_IsFieldNull(Handle:query, field);
+
+/**
+ * Returns the length of a field's data in the current row of a result
+ * set. This only needs to be called for strings to determine how many
+ * bytes to use. Note that the return value does not include the null
+ * terminator.
+ *
+ * @param query A query (or statement) Handle.
+ * @param field The field index (starting from 0).
+ * @return Number of bytes for the field's data size.
+ * @error Invalid query Handle or field index or no
+ * current result set.
+ */
+native SQL_FetchSize(Handle:query, field);
+
+/**
+ * Binds a parameter in a prepared statement to a given integer value.
+ *
+ * @param statement A statement (prepared query) Handle.
+ * @param param The parameter index (starting from 0).
+ * @param number The number to bind.
+ * @param signed True to bind the number as signed, false to
+ * bind it as unsigned.
+ * @noreturn
+ * @error Invalid statement Handle or parameter index, or
+ * SQL error.
+ */
+native SQL_BindParamInt(Handle:statement, param, number, bool:signed=true);
+
+/**
+ * Binds a parameter in a prepared statement to a given float value.
+ *
+ * @param statement A statement (prepared query) Handle.
+ * @param param The parameter index (starting from 0).
+ * @param value The float number to bind.
+ * @noreturn
+ * @error Invalid statement Handle or parameter index, or
+ * SQL error.
+ */
+native SQL_BindParamFloat(Handle:statement, param, Float:value);
+
+/**
+ * Binds a parameter in a prepared statement to a given string value.
+ *
+ * @param statement A statement (prepared query) Handle.
+ * @param param The parameter index (starting from 0).
+ * @param value The string to bind.
+ * @param copy Whether or not SourceMod should copy the value
+ * locally if necessary. If the string contents
+ * won't change before calling SQL_Execute(), this
+ * can be set to false for optimization.
+ * @noreturn
+ * @error Invalid statement Handle or parameter index, or
+ * SQL error.
+ */
+native SQL_BindParamString(Handle:statement, param, const String:value[], bool:copy);
+
+/**
+ * Executes a prepared statement. All parameters must be bound beforehand.
+ *
+ * @param statement A statement (prepared query) Handle.
+ * @return True on success, false on failure.
+ * @error Invalid statement Handle.
+ */
+native bool:SQL_Execute(Handle:statement);
+
+/**
+ * Locks a database so threading operations will not interrupt.
+ *
+ * If you are using a database Handle for both threading and non-threading,
+ * this MUST be called before doing any set of non-threading DB operations.
+ * Otherwise you risk corrupting the database driver's memory or network
+ * connection.
+ *
+ * Leaving a lock on a database and then executing a threaded query results
+ * in a dead lock! Make sure to call SQL_UnlockDatabase()!
+ *
+ * If the lock cannot be acquired, the main thread will pause until the
+ * threaded operation has concluded.
+ *
+ * @param database A database Handle.
+ * @noreturn
+ * @error Invalid database Handle.
+ */
+native SQL_LockDatabase(Handle:database);
+
+/**
+ * Unlocks a database so threading operations may continue.
+ *
+ * @param database A database Handle.
+ * @noreturn
+ * @error Invalid database Handle.
+ */
+native SQL_UnlockDatabase(Handle:database);
+
+/**
+ * General callback for threaded SQL stuff.
+ *
+ * @param owner Parent object of the Handle (or INVALID_HANDLE if none).
+ * @param hndl Handle to the child object (or INVALID_HANDLE if none).
+ * @param error Error string if there was an error. The error could be
+ * empty even if an error condition exists, so it is important
+ * to check the actual Handle value instead.
+ * @param data Data passed in via the original threaded invocation.
+ * @param
+ */
+functag public SQLTCallback(Handle:owner, Handle:hndl, const String:error[], any:data);
+
+/**
+ * Tells whether two database handles both point to the same database
+ * connection.
+ *
+ * @param hndl1 First database Handle.
+ * @param hndl2 Second database Handle.
+ * @return True if the Handles point to the same
+ * connection, false otherwise.
+ * @error Invalid Handle.
+ */
+native bool:SQL_IsSameConnection(Handle:hndl1, Handle:hndl2);
+
+/**
+ * Connects to a database via a thread. This can be used instead of
+ * SQL_Connect() if you wish for non-blocking functionality.
+ *
+ * It is not necessary to use this to use threaded queries. However, if you
+ * don't (or you mix threaded/non-threaded queries), you should see
+ * SQL_LockDatabase().
+ *
+ * @param callback Callback; new Handle will be in hndl, owner is the driver.
+ * If no driver was found, the owner is INVALID_HANDLE.
+ * @param name Database name.
+ * @param data Extra data value to pass to the callback.
+ * @noreturn
+ */
+native SQL_TConnect(SQLTCallback:callback, const String:name[]="default", any:data=0);
+
+/**
+ * Executes a simple query via a thread. The query Handle is passed through
+ * the callback.
+ *
+ * The database Handle returned through the callback is always a new Handle,
+ * and if necessary, SQL_IsSameConnection() should be used to test against
+ * other conenctions.
+ *
+ * The query Handle returned through the callback is temporary and destroyed
+ * at the end of the callback. If you need to hold onto it, use CloneHandle().
+ *
+ * @param database A database Handle.
+ * @param callback Callback; database is in "owner" and the query Handle
+ * is passed in "hndl".
+ * @param query Query string.
+ * @param data Extra data value to pass to the callback.
+ * @param prio Priority queue to use.
+ * @noreturn
+ * @error Invalid database Handle.
+ */
+native SQL_TQuery(Handle:database, SQLTCallback:callback, const String:query[], any:data=0, DBPriority:prio=DBPrio_Normal);
+
+/**
+ * Creates a new transaction object. A transaction object is a list of queries
+ * that can be sent to the database thread and executed as a single transaction.
+ *
+ * @return A transaction handle.
+ */
+native Handle:SQL_CreateTransaction();
+
+/**
+ * Adds a query to a transaction object.
+ *
+ * @param txn A transaction handle.
+ * @param query Query string.
+ * @param data Extra data value to pass to the final callback.
+ * @return The index of the query in the transaction's query list.
+ * @error Invalid transaction handle.
+ */
+native SQL_AddQuery(Handle:txn, const String:query[], any:data=0);
+
+/**
+ * Callback for a successful transaction.
+ *
+ * @param db Database handle.
+ * @param data Data value passed to SQL_ExecuteTransaction().
+ * @param numQueries Number of queries executed in the transaction.
+ * @param results An array of Query handle results, one for each of numQueries. They are closed automatically.
+ * @param queryData An array of each data value passed to SQL_AddQuery().
+ * @noreturn
+ */
+functag public SQLTxnSuccess(Handle:db, any:data, numQueries, Handle:results[], any:queryData[]);
+
+/**
+ * Callback for a failed transaction.
+ *
+ * @param db Database handle.
+ * @param data Data value passed to SQL_ExecuteTransaction().
+ * @param numQueries Number of queries executed in the transaction.
+ * @param error Error message.
+ * @param failIndex Index of the query that failed, or -1 if something else.
+ * @param queryData An array of each data value passed to SQL_AddQuery().
+ * @noreturn
+ */
+functag public SQLTxnFailure(Handle:db, any:data, numQueries, const String:error[], failIndex, any:queryData[]);
+
+/**
+ * Sends a transaction to the database thread. The transaction handle is
+ * automatically closed. When the transaction completes, the optional
+ * callback is invoked.
+ *
+ * @param db A database handle.
+ * @param txn A transaction handle.
+ * @param onSuccess An optional callback to receive a successful transaction.
+ * @param onError An optional callback to receive an error message.
+ * @param data An optional value to pass to callbacks.
+ * @param prio Priority queue to use.
+ * @noreturn
+ * @error An invalid handle.
+ */
+native SQL_ExecuteTransaction(
+ Handle:db,
+ Handle:txn,
+ SQLTxnSuccess:onSuccess=SQLTxnSuccess:-1,
+ SQLTxnFailure:onError=SQLTxnFailure:-1,
+ any:data=0,
+ DBPriority:priority=DBPrio_Normal);
diff --git a/sourcemod-1.5-dev/scripting/include/entity.inc b/sourcemod-1.5-dev/scripting/include/entity.inc
new file mode 100644
index 0000000..d33a3b8
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/entity.inc
@@ -0,0 +1,738 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2011 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _entity_included
+ #endinput
+#endif
+#define _entity_included
+
+/**
+ * Property types for entities.
+ */
+enum PropType
+{
+ Prop_Send = 0, /**< This property is networked. */
+ Prop_Data = 1, /**< This property is for save game data fields. */
+};
+
+/**
+ * @section For more information on these, see the HL2SDK (public/edict.h)
+ */
+#define FL_EDICT_CHANGED (1<<0) /**< Game DLL sets this when the entity state changes
+ Mutually exclusive with FL_EDICT_PARTIAL_CHANGE. */
+#define FL_EDICT_FREE (1<<1) /**< this edict if free for reuse */
+#define FL_EDICT_FULL (1<<2) /**< this is a full server entity */
+#define FL_EDICT_FULLCHECK (0<<0) /**< call ShouldTransmit() each time, this is a fake flag */
+#define FL_EDICT_ALWAYS (1<<3) /**< always transmit this entity */
+#define FL_EDICT_DONTSEND (1<<4) /**< don't transmit this entity */
+#define FL_EDICT_PVSCHECK (1<<5) /**< always transmit entity, but cull against PVS */
+#define FL_EDICT_PENDING_DORMANT_CHECK (1<<6)
+#define FL_EDICT_DIRTY_PVS_INFORMATION (1<<7)
+#define FL_FULL_EDICT_CHANGED (1<<8)
+
+enum PropFieldType
+{
+ PropField_Unsupported, /**< The type is unsupported. */
+ PropField_Integer, /**< Valid for SendProp and Data fields */
+ PropField_Float, /**< Valid for SendProp and Data fields */
+ PropField_Entity, /**< Valid for Data fields only (SendProp shows as int) */
+ PropField_Vector, /**< Valid for SendProp and Data fields */
+ PropField_String, /**< Valid for SendProp and Data fields */
+ PropField_String_T, /**< Valid for Data fields. Read only.
+ Note that the size of a string_t is dynamic, and
+ thus FindDataMapOffs() will return the constant size
+ of the string_t container (which is 32 bits right now).
+ */
+};
+
+/**
+ * @endsection
+ */
+
+/**
+ * Returns the maximum number of entities.
+ *
+ * @return Maximum number of entities.
+ */
+native GetMaxEntities();
+
+/**
+ * Returns the number of entities in the server.
+ *
+ * @return Number of entities in the server.
+ */
+native GetEntityCount();
+
+/**
+ * Returns whether or not an entity is valid. Returns false
+ * if there is no matching CBaseEntity for this edict index.
+ *
+ * @param edict Index of the entity/edict.
+ * @return True if valid, false otherwise.
+ */
+native bool:IsValidEntity(edict);
+
+/**
+ * Returns whether or not an edict index is valid.
+ *
+ * @param edict Index of the edict.
+ * @return True if valid, false otherwise.
+ */
+native bool:IsValidEdict(edict);
+
+/**
+ * Returns whether or not an entity is a valid networkable edict.
+ *
+ * @param edict Index of the edict.
+ * @return True if networkable, false if invalid or not networkable.
+ */
+native bool:IsEntNetworkable(edict);
+
+/**
+ * Creates a new edict (the basis of a networkable entity)
+ *
+ * @return Index of the edict, 0 on failure.
+ */
+native CreateEdict();
+
+/**
+ * Removes an edict from the world.
+ *
+ * @param edict Index of the edict.
+ * @noreturn
+ * @error Invalid edict index.
+ */
+native RemoveEdict(edict);
+
+/**
+ * Returns the flags on an edict. These are not the same as entity flags.
+ *
+ * @param edict Index of the entity.
+ * @return Edict flags.
+ * @error Invalid edict index.
+ */
+native GetEdictFlags(edict);
+
+/**
+ * Sets the flags on an edict. These are not the same as entity flags.
+ *
+ * @param edict Index of the entity.
+ * @param flags Flags to set.
+ * @noreturn
+ * @error Invalid edict index.
+ */
+native SetEdictFlags(edict, flags);
+
+/**
+ * Retrieves an edict classname.
+ *
+ * @param edict Index of the entity.
+ * @param clsname Buffer to store the classname.
+ * @param maxlength Maximum length of the buffer.
+ * @return True on success, false if there is no classname set.
+ */
+native bool:GetEdictClassname(edict, String:clsname[], maxlength);
+
+/**
+ * Retrieves an entity's networkable serverclass name.
+ * This is not the same as the classname and is used for networkable state changes.
+ *
+ * @param edict Index of the entity.
+ * @param clsname Buffer to store the serverclass name.
+ * @param maxlength Maximum lnegth of the buffer.
+ * @return True on success, false if the edict is not networkable.
+ * @error Invalid edict index.
+ */
+native bool:GetEntityNetClass(edict, String:clsname[], maxlength);
+
+/**
+ * @section Entity offset functions
+ *
+ * Offsets should be specified in byte distance from the CBaseEntity
+ * structure, not short (double byte) or integer (four byte) multiples.
+ * It is somewhat common practice to use offsets aligned to their final
+ * type, and thus make sure you are not falling to this error in SourceMod.
+ * For example, if your "integer-aligned" offset was 119, your byte-aligned
+ * offset is 119*4, or 476.
+
+ * Specifying incorrect offsets or the incorrect data type for an offset
+ * can have fatal consequences. If you are hardcoding offsets, and the
+ * layout of CBaseEntity does not match, you can easily crash the server.
+ *
+ * The reasonable bounds for offsets is greater than or equal to 0 and
+ * below 32768. Offsets out of these bounds will throw an error. However,
+ * this does not represent any real range, it is simply a sanity check for
+ * illegal values. Any range outside of the CBaseEntity structure's private
+ * size will cause undefined behaviour or even crash.
+ */
+
+/**
+ * Marks an entity as state changed. This can be useful if you set an offset
+ * and wish for it to be immediately changed over the network. By default this
+ * is not done for offset setting functions.
+ *
+ * @param edict Index to the edict.
+ * @param offset Offset to mark as changed. If 0,
+ * the entire edict is marked as changed.
+ * @noreturn
+ * @error Invalid entity or offset out of bounds.
+ */
+native ChangeEdictState(edict, offset = 0);
+
+/**
+ * Peeks into an entity's object data and retrieves the integer value at
+ * the given offset.
+ *
+ * @param entity Edict index.
+ * @param offset Offset to use.
+ * @param size Number of bytes to read (valid values are 1, 2, or 4).
+ * @return Value at the given memory location.
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+native GetEntData(entity, offset, size=4);
+
+/**
+ * Peeks into an entity's object data and sets the integer value at
+ * the given offset.
+ *
+ * @param entity Edict index.
+ * @param offset Offset to use.
+ * @param value Value to set.
+ * @param size Number of bytes to write (valid values are 1, 2, or 4).
+ * @param changeState If true, change will be sent over the network.
+ * @return Value at the given memory location.
+ * @error Invalid entity or offset out of reasonable bounds.
+ * @noreturn
+ */
+native SetEntData(entity, offset, any:value, size=4, bool:changeState=false);
+
+/**
+ * Peeks into an entity's object data and retrieves the float value at
+ * the given offset.
+ *
+ * @param entity Edict index.
+ * @param offset Offset to use.
+ * @return Value at the given memory location.
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+native Float:GetEntDataFloat(entity, offset);
+
+/**
+ * Peeks into an entity's object data and sets the float value at
+ * the given offset.
+ *
+ * @param entity Edict index.
+ * @param offset Offset to use.
+ * @param value Value to set.
+ * @param changeState If true, change will be sent over the network.
+ * @return Value at the given memory location.
+ * @error Invalid entity or offset out of reasonable bounds.
+ * @noreturn
+ */
+native SetEntDataFloat(entity, offset, Float:value, bool:changeState=false);
+
+/**
+ * This function is deprecated. Use GetEntDataEnt2 instead, for
+ * reasons explained in the notes.
+ *
+ * Note: This function returns 0 on failure, which may be misleading,
+ * as the number 0 is also used for the world entity index.
+ *
+ * Note: This function makes no attempt to validate the returned
+ * entity, and in fact, it could be garbage or completely unexpected.
+ *
+ * @param entity Edict index.
+ * @param offset Offset to use.
+ * @return Entity index at the given location, or 0 if none.
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+#pragma deprecated Use GetEntDataEnt2() instead.
+native GetEntDataEnt(entity, offset);
+
+/**
+ * This function is deprecated. Use SetEntDataEnt2 instead, for
+ * reasons explained in the notes.
+ *
+ * Note: This function uses 0 as an indicator to unset data, but
+ * 0 is also the world entity index. Thus, a property cannot
+ * be set to the world entity using this native.
+ *
+ * @param entity Edict index.
+ * @param offset Offset to use.
+ * @param other Entity index to set, or 0 to clear.
+ * @param changeState If true, change will be sent over the network.
+ * @noreturn
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+#pragma deprecated Use SetEntDataEnt2() instead.
+native SetEntDataEnt(entity, offset, other, bool:changeState=false);
+
+/**
+ * Peeks into an entity's object data and retrieves the entity index
+ * at the given offset.
+ *
+ * Note: This will only work on offsets that are stored as "entity
+ * handles" (which usually looks like m_h* in properties). These
+ * are not SourceMod Handles, but internal Source structures.
+ *
+ * @param entity Edict index.
+ * @param offset Offset to use.
+ * @return Entity index at the given location. If there is no entity,
+ * or the stored entity is invalid, then -1 is returned.
+ * @error Invalid input entity, or offset out of reasonable bounds.
+ */
+native GetEntDataEnt2(entity, offset);
+
+/**
+ * Peeks into an entity's object data and sets the entity index at the
+ * given offset.
+ *
+ * Note: This will only work on offsets that are stored as "entity
+ * handles" (which usually looks like m_h* in properties). These
+ * are not SourceMod Handles, but internal Source structures.
+ *
+ * @param entity Edict index.
+ * @param offset Offset to use.
+ * @param other Entity index to set, or -1 to clear.
+ * @param changeState If true, change will be sent over the network.
+ * @noreturn
+ * @error Invalid input entity, or offset out of reasonable bounds.
+ */
+native SetEntDataEnt2(entity, offset, other, bool:changeState=false);
+
+/**
+ * Peeks into an entity's object data and retrieves the vector at the
+ * given offset.
+ * @note Both a Vector and a QAngle are three floats. This is a
+ * convenience function and will work with both types.
+ *
+ * @param entity Edict index.
+ * @param offset Offset to use.
+ * @param vec Vector buffer to store data in.
+ * @noreturn
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+native GetEntDataVector(entity, offset, Float:vec[3]);
+
+/**
+ * Peeks into an entity's object data and sets the vector at the given
+ * offset.
+ * @note Both a Vector and a QAngle are three floats. This is a
+ * convenience function and will work with both types.
+ *
+ * @param entity Edict index.
+ * @param offset Offset to use.
+ * @param vec Vector to set.
+ * @param changeState If true, change will be sent over the network.
+ * @noreturn
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+native SetEntDataVector(entity, offset, const Float:vec[3], bool:changeState=false);
+
+/**
+ * Peeks into an entity's object data and retrieves the string at
+ * the given offset.
+ *
+ * @param entity Edict index.
+ * @param offset Offset to use.
+ * @param buffer Destination string buffer.
+ * @param maxlen Maximum length of output string buffer.
+ * @return Number of non-null bytes written.
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+native GetEntDataString(entity, offset, String:buffer[], maxlen);
+
+/**
+ * Peeks into an entity's object data and sets the string at
+ * the given offset.
+ *
+ * @param entity Edict index.
+ * @param offset Offset to use.
+ * @param buffer String to set.
+ * @param maxlen Maximum length of bytes to write.
+ * @param changeState If true, change will be sent over the network.
+ * @return Number of non-null bytes written.
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+native SetEntDataString(entity, offset, const String:buffer[], maxlen, bool:changeState=false);
+
+/**
+ * @endsection
+ */
+
+/**
+ * Given a ServerClass name, finds a networkable send property offset.
+ * This information is cached for future calls.
+ *
+ * Note, this function may return offsets that do not work!
+ * If a property is nested beneath a parent object, the resulting offset
+ * will be invalid for direct use with data functions. Therefore, you
+ * should use FindSendPropInfo() instead. An example of such a property is
+ * CTFPlayer::DT_LocalPlayer.m_nDisguiseClass on Team Fortress.
+ *
+ * @param cls Classname.
+ * @param prop Property name.
+ * @return An offset, or -1 on failure.
+ */
+native FindSendPropOffs(const String:cls[], const String:prop[]);
+
+/**
+ * Given a ServerClass name, finds a networkable send property offset.
+ * This information is cached for future calls.
+ *
+ * Note: This function will correctly compute nested offsets, unlike
+ * FindSendPropOffs(). YOU SHOULD NOT use this function to self-compute
+ * nested offsets. For example, it is okay to add indexes for arrays,
+ * but not to add DT_LocalPlayer to m_nDisguiseClass.
+ *
+ * @param cls Classname.
+ * @param prop Property name.
+ * @param type Optional parameter to store the type.
+ * @param num_bits Optional parameter to store the number of bits the field
+ * uses, if applicable (otherwise 0 is stored). The number
+ * of bits varies for integers and floats, and is always 0
+ * for strings.
+ * @param local_offset Optional parameter to store the local offset, as
+ * FindSendPropOffs() would return.
+ * @return On success, returns an absolutely computed offset.
+ * If no offset is available, 0 is returned.
+ * If the property is not found, -1 is returned.
+ */
+native FindSendPropInfo(const String:cls[],
+ const String:prop[],
+ &PropFieldType:type=PropFieldType:0,
+ &num_bits=0,
+ &local_offset=0);
+
+/**
+ * Given an entity, finds a datamap property offset.
+ * This information is cached for future calls.
+ *
+ * @param entity Entity index.
+ * @param prop Property name.
+ * @param type Optional parameter to store the type.
+ * @param num_bits Optional parameter to store the number of bits the field
+ * uses. The bit count will either be 1 (for boolean) or
+ * divisible by 8 (including 0 if unknown).
+ * @return An offset, or -1 on failure.
+ */
+native FindDataMapOffs(entity,
+ const String:prop[],
+ &PropFieldType:type=PropFieldType:0,
+ &num_bits=0);
+
+/**
+ * Given an entity, finds a nested datamap property offset.
+ * This information is cached for future calls.
+ *
+ * @param entity Entity index.
+ * @param prop Property name.
+ * @param type Optional parameter to store the type.
+ * @param num_bits Optional parameter to store the number of bits the field
+ * uses. The bit count will either be 1 (for boolean) or
+ * divisible by 8 (including 0 if unknown).
+ * @param local_offset Optional parameter to store the local offset, as
+ * FindDataMapOffs() would return.
+ * @return An offset, or -1 on failure.
+ */
+native FindDataMapInfo(entity,
+ const String:prop[],
+ &PropFieldType:type=PropFieldType:0,
+ &num_bits=0,
+ &local_offset=0);
+
+/**
+ * Wrapper function for finding a send property for a particular entity.
+ *
+ * @param ent Entity index.
+ * @param prop Property name.
+ * @param actual Defaults to false for backwards compatibility.
+ * If true, the newer FindSendPropInfo() function
+ * is used instead.
+ * @return An offset, or -1 on failure.
+ */
+stock GetEntSendPropOffs(ent, const String:prop[], bool:actual=false)
+{
+ decl String:cls[64];
+
+ if (!GetEntityNetClass(ent, cls, sizeof(cls)))
+ {
+ return -1;
+ }
+
+ if (actual)
+ {
+ return FindSendPropInfo(cls, prop);
+ }
+ else
+ {
+ return FindSendPropOffs(cls, prop);
+ }
+}
+
+/**
+ * Retrieves an integer value from an entity's property.
+ *
+ * This function is considered safer and more robust over GetEntData,
+ * because it performs strict offset checking and typing rules.
+ *
+ * @param entity Entity/edict index.
+ * @param type Property type.
+ * @param prop Property name.
+ * @param size Number of bytes to write (valid values are 1, 2, or 4).
+ * This value is auto-detected, and the size parameter is
+ * only used as a fallback in case detection fails.
+ * @param element Element # (starting from 0) if property is an array.
+ * @return Value at the given property offset.
+ * @error Invalid entity or property not found.
+ */
+native GetEntProp(entity, PropType:type, const String:prop[], size=4, element=0);
+
+/**
+ * Sets an integer value in an entity's property.
+ *
+ * This function is considered safer and more robust over SetEntData,
+ * because it performs strict offset checking and typing rules.
+ *
+ * @param entity Entity/edict index.
+ * @param type Property type.
+ * @param prop Property name.
+ * @param value Value to set.
+ * @param size Number of bytes to write (valid values are 1, 2, or 4).
+ * This value is auto-detected, and the size parameter is
+ * only used as a fallback in case detection fails.
+ * @param element Element # (starting from 0) if property is an array.
+ * @error Invalid entity or offset out of reasonable bounds.
+ * @noreturn
+ */
+native SetEntProp(entity, PropType:type, const String:prop[], any:value, size=4, element=0);
+
+/**
+ * Retrieves a float value from an entity's property.
+ *
+ * This function is considered safer and more robust over GetEntDataFloat,
+ * because it performs strict offset checking and typing rules.
+ *
+ * @param entity Entity/edict index.
+ * @param type Property type.
+ * @param prop Property name.
+ * @param element Element # (starting from 0) if property is an array.
+ * @return Value at the given property offset.
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+native Float:GetEntPropFloat(entity, PropType:type, const String:prop[], element=0);
+
+/**
+ * Sets a float value in an entity's property.
+ *
+ * This function is considered safer and more robust over SetEntDataFloat,
+ * because it performs strict offset checking and typing rules.
+ *
+ * @param entity Entity/edict index.
+ * @param type Property type.
+ * @param prop Property name.
+ * @param value Value to set.
+ * @param element Element # (starting from 0) if property is an array.
+ * @noreturn
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+native SetEntPropFloat(entity, PropType:type, const String:prop[], Float:value, element=0);
+
+/**
+ * Retrieves an entity index from an entity's property.
+ *
+ * This function is considered safer and more robust over GetEntDataEnt*,
+ * because it performs strict offset checking and typing rules.
+ *
+ * @param entity Entity/edict index.
+ * @param type Property type.
+ * @param prop Property name.
+ * @param element Element # (starting from 0) if property is an array.
+ * @return Entity index at the given property.
+ * If there is no entity, or the entity is not valid,
+ * then -1 is returned.
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+native GetEntPropEnt(entity, PropType:type, const String:prop[], element=0);
+
+/**
+ * Sets an entity index in an entity's property.
+ *
+ * This function is considered safer and more robust over SetEntDataEnt*,
+ * because it performs strict offset checking and typing rules.
+ *
+ * @param entity Entity/edict index.
+ * @param type Property type.
+ * @param prop Property name.
+ * @param other Entity index to set, or -1 to unset.
+ * @param element Element # (starting from 0) if property is an array.
+ * @noreturn
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+native SetEntPropEnt(entity, PropType:type, const String:prop[], other, element=0);
+
+/**
+ * Retrieves a vector of floats from an entity, given a named network property.
+ *
+ * This function is considered safer and more robust over GetEntDataVector,
+ * because it performs strict offset checking and typing rules.
+ *
+ * @param entity Entity/edict index.
+ * @param type Property type.
+ * @param prop Property name.
+ * @param vec Vector buffer to store data in.
+ * @param element Element # (starting from 0) if property is an array.
+ * @noreturn
+ * @error Invalid entity, property not found, or property not
+ * actually a vector data type.
+ */
+native GetEntPropVector(entity, PropType:type, const String:prop[], Float:vec[3], element=0);
+
+/**
+ * Sets a vector of floats in an entity, given a named network property.
+ *
+ * This function is considered safer and more robust over SetEntDataVector,
+ * because it performs strict offset checking and typing rules.
+ *
+ * @param entity Entity/edict index.
+ * @param type Property type.
+ * @param prop Property name.
+ * @param vec Vector to set.
+ * @param element Element # (starting from 0) if property is an array.
+ * @noreturn
+ * @error Invalid entity, property not found, or property not
+ * actually a vector data type.
+ */
+native SetEntPropVector(entity, PropType:type, const String:prop[], const Float:vec[3], element=0);
+
+/**
+ * Gets a network property as a string.
+ *
+ * @param entity Edict index.
+ * @param type Property type.
+ * @param prop Property to use.
+ * @param buffer Destination string buffer.
+ * @param maxlen Maximum length of output string buffer.
+ * @param element Element # (starting from 0) if property is an array.
+ * @return Number of non-null bytes written.
+ * @error Invalid entity, offset out of reasonable bounds, or property is not a valid string.
+ */
+native GetEntPropString(entity, PropType:type, const String:prop[], String:buffer[], maxlen, element=0);
+
+/**
+ * Sets a network property as a string.
+ *
+ * This cannot set property fields of type PropField_String_T (such as "m_target").
+ * To set such fields, you should use DispatchKeyValue() from SDKTools.
+ *
+ * @param entity Edict index.
+ * @param type Property type.
+ * @param prop Property to use.
+ * @param buffer String to set.
+ * @return Number of non-null bytes written.
+ * @error Invalid entity, offset out of reasonable bounds, or property is not a valid string.
+ */
+native SetEntPropString(entity, PropType:type, const String:prop[], const String:buffer[]);
+
+/**
+ * Retrieves the count of values that an entity property's array can store.
+ *
+ * @param entity Entity/edict index.
+ * @param type Property type.
+ * @param prop Property name.
+ * @return Size of array (in elements) or 1 if property is not an array.
+ * @error Invalid entity or property not found.
+ */
+native GetEntPropArraySize(entity, PropType:type, const String:prop[]);
+
+/**
+ * Copies an array of cells from an entity at a given offset.
+ *
+ * @param entity Entity index.
+ * @param offset Offset to use.
+ * @param array Array to read into.
+ * @param arraySize Number of values to read.
+ * @param dataSize Size of each value in bytes (1, 2, or 4).
+ * @noreturn
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+stock GetEntDataArray(entity, offset, array[], arraySize, dataSize=4)
+{
+ for (new i=0; i<arraySize; i++)
+ {
+ array[i] = GetEntData(entity, offset + i*dataSize, dataSize)
+ }
+}
+
+/**
+ * Copies an array of cells to an entity at a given offset.
+ *
+ * @param entity Entity index.
+ * @param offset Offset to use.
+ * @param array Array of values to copy.
+ * @param arraySize Number of values to copy.
+ * @param dataSize Size of each value in bytes (1, 2, or 4).
+ * @param changeState True to set the network state as changed; false otherwise.
+ * @noreturn
+ * @error Invalid entity or offset out of reasonable bounds.
+ */
+stock SetEntDataArray(entity, offset, const array[], arraySize, dataSize=4, bool:changeState=false)
+{
+ for (new i=0; i<arraySize; i++)
+ {
+ SetEntData(entity, offset + i*dataSize, array[i], dataSize, changeState);
+ }
+}
+
+/**
+ * Gets the memory address of an entity.
+ *
+ * @param entity Entity index.
+ * @return Address of the entity.
+ * @error Invalid entity.
+ */
+native Address:GetEntityAddress(entity);
+
+/**
+ * Retrieves the classname of an entity.
+ * This is like GetEdictClassname(), except it works for ALL
+ * entities, not just edicts.
+ *
+ * @param entity Index of the entity.
+ * @param clsname Buffer to store the classname.
+ * @param maxlength Maximum length of the buffer.
+ * @return True on success, false if there is no classname set.
+ */
+stock bool:GetEntityClassname(entity, String:clsname[], maxlength)
+{
+ return !!GetEntPropString(entity, Prop_Data, "m_iClassname", clsname, maxlength);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/entity_prop_stocks.inc b/sourcemod-1.5-dev/scripting/include/entity_prop_stocks.inc
new file mode 100644
index 0000000..7f22b50
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/entity_prop_stocks.inc
@@ -0,0 +1,559 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _entity_prop_stocks_included
+ #endinput
+#endif
+#define _entity_prop_stocks_included
+
+enum MoveType
+{
+ MOVETYPE_NONE = 0, /**< never moves */
+ MOVETYPE_ISOMETRIC, /**< For players */
+ MOVETYPE_WALK, /**< Player only - moving on the ground */
+ MOVETYPE_STEP, /**< gravity, special edge handling -- monsters use this */
+ MOVETYPE_FLY, /**< No gravity, but still collides with stuff */
+ MOVETYPE_FLYGRAVITY, /**< flies through the air + is affected by gravity */
+ MOVETYPE_VPHYSICS, /**< uses VPHYSICS for simulation */
+ MOVETYPE_PUSH, /**< no clip to world, push and crush */
+ MOVETYPE_NOCLIP, /**< No gravity, no collisions, still do velocity/avelocity */
+ MOVETYPE_LADDER, /**< Used by players only when going onto a ladder */
+ MOVETYPE_OBSERVER, /**< Observer movement, depends on player's observer mode */
+ MOVETYPE_CUSTOM, /**< Allows the entity to describe its own physics */
+};
+
+enum RenderMode
+{
+ RENDER_NORMAL, /**< src */
+ RENDER_TRANSCOLOR, /**< c*a+dest*(1-a) */
+ RENDER_TRANSTEXTURE, /**< src*a+dest*(1-a) */
+ RENDER_GLOW, /**< src*a+dest -- No Z buffer checks -- Fixed size in screen space */
+ RENDER_TRANSALPHA, /**< src*srca+dest*(1-srca) */
+ RENDER_TRANSADD, /**< src*a+dest */
+ RENDER_ENVIRONMENTAL, /**< not drawn, used for environmental effects */
+ RENDER_TRANSADDFRAMEBLEND, /**< use a fractional frame value to blend between animation frames */
+ RENDER_TRANSALPHAADD, /**< src + dest*(1-a) */
+ RENDER_WORLDGLOW, /**< Same as kRenderGlow but not fixed size in screen space */
+ RENDER_NONE, /**< Don't render. */
+};
+
+enum RenderFx
+{
+ RENDERFX_NONE = 0,
+ RENDERFX_PULSE_SLOW,
+ RENDERFX_PULSE_FAST,
+ RENDERFX_PULSE_SLOW_WIDE,
+ RENDERFX_PULSE_FAST_WIDE,
+ RENDERFX_FADE_SLOW,
+ RENDERFX_FADE_FAST,
+ RENDERFX_SOLID_SLOW,
+ RENDERFX_SOLID_FAST,
+ RENDERFX_STROBE_SLOW,
+ RENDERFX_STROBE_FAST,
+ RENDERFX_STROBE_FASTER,
+ RENDERFX_FLICKER_SLOW,
+ RENDERFX_FLICKER_FAST,
+ RENDERFX_NO_DISSIPATION,
+ RENDERFX_DISTORT, /**< Distort/scale/translate flicker */
+ RENDERFX_HOLOGRAM, /**< kRenderFxDistort + distance fade */
+ RENDERFX_EXPLODE, /**< Scale up really big! */
+ RENDERFX_GLOWSHELL, /**< Glowing Shell */
+ RENDERFX_CLAMP_MIN_SCALE, /**< Keep this sprite from getting very small (SPRITES only!) */
+ RENDERFX_ENV_RAIN, /**< for environmental rendermode, make rain */
+ RENDERFX_ENV_SNOW, /**< " " " , make snow */
+ RENDERFX_SPOTLIGHT, /**< TEST CODE for experimental spotlight */
+ RENDERFX_RAGDOLL, /**< HACKHACK: TEST CODE for signalling death of a ragdoll character */
+ RENDERFX_PULSE_FAST_WIDER,
+ RENDERFX_MAX
+};
+
+// These defines are for client button presses.
+#define IN_ATTACK (1 << 0)
+#define IN_JUMP (1 << 1)
+#define IN_DUCK (1 << 2)
+#define IN_FORWARD (1 << 3)
+#define IN_BACK (1 << 4)
+#define IN_USE (1 << 5)
+#define IN_CANCEL (1 << 6)
+#define IN_LEFT (1 << 7)
+#define IN_RIGHT (1 << 8)
+#define IN_MOVELEFT (1 << 9)
+#define IN_MOVERIGHT (1 << 10)
+#define IN_ATTACK2 (1 << 11)
+#define IN_RUN (1 << 12)
+#define IN_RELOAD (1 << 13)
+#define IN_ALT1 (1 << 14)
+#define IN_ALT2 (1 << 15)
+#define IN_SCORE (1 << 16) /**< Used by client.dll for when scoreboard is held down */
+#define IN_SPEED (1 << 17) /**< Player is holding the speed key */
+#define IN_WALK (1 << 18) /**< Player holding walk key */
+#define IN_ZOOM (1 << 19) /**< Zoom key for HUD zoom */
+#define IN_WEAPON1 (1 << 20) /**< weapon defines these bits */
+#define IN_WEAPON2 (1 << 21) /**< weapon defines these bits */
+#define IN_BULLRUSH (1 << 22)
+#define IN_GRENADE1 (1 << 23) /**< grenade 1 */
+#define IN_GRENADE2 (1 << 24) /**< grenade 2 */
+#define IN_ATTACK3 (1 << 25)
+
+// Note: these are only for use with GetEntityFlags and SetEntityFlags
+// and may not match the game's actual, internal m_fFlags values.
+// PLAYER SPECIFIC FLAGS FIRST BECAUSE WE USE ONLY A FEW BITS OF NETWORK PRECISION
+#define FL_ONGROUND (1 << 0) /**< At rest / on the ground */
+#define FL_DUCKING (1 << 1) /**< Player flag -- Player is fully crouched */
+#define FL_WATERJUMP (1 << 2) /**< player jumping out of water */
+#define FL_ONTRAIN (1 << 3) /**< Player is _controlling_ a train, so movement commands should be ignored on client during prediction. */
+#define FL_INRAIN (1 << 4) /**< Indicates the entity is standing in rain */
+#define FL_FROZEN (1 << 5) /**< Player is frozen for 3rd person camera */
+#define FL_ATCONTROLS (1 << 6) /**< Player can't move, but keeps key inputs for controlling another entity */
+#define FL_CLIENT (1 << 7) /**< Is a player */
+#define FL_FAKECLIENT (1 << 8) /**< Fake client, simulated server side; don't send network messages to them */
+// NOTE if you move things up, make sure to change this value
+#define PLAYER_FLAG_BITS 9
+// NON-PLAYER SPECIFIC (i.e., not used by GameMovement or the client .dll ) -- Can still be applied to players, though
+#define FL_INWATER (1 << 9) /**< In water */
+#define FL_FLY (1 << 10) /**< Changes the SV_Movestep() behavior to not need to be on ground */
+#define FL_SWIM (1 << 11) /**< Changes the SV_Movestep() behavior to not need to be on ground (but stay in water) */
+#define FL_CONVEYOR (1 << 12)
+#define FL_NPC (1 << 13)
+#define FL_GODMODE (1 << 14)
+#define FL_NOTARGET (1 << 15)
+#define FL_AIMTARGET (1 << 16) /**< set if the crosshair needs to aim onto the entity */
+#define FL_PARTIALGROUND (1 << 17) /**< not all corners are valid */
+#define FL_STATICPROP (1 << 18) /**< Eetsa static prop! */
+#define FL_GRAPHED (1 << 19) /**< worldgraph has this ent listed as something that blocks a connection */
+#define FL_GRENADE (1 << 20)
+#define FL_STEPMOVEMENT (1 << 21) /**< Changes the SV_Movestep() behavior to not do any processing */
+#define FL_DONTTOUCH (1 << 22) /**< Doesn't generate touch functions, generates Untouch() for anything it was touching when this flag was set */
+#define FL_BASEVELOCITY (1 << 23) /**< Base velocity has been applied this frame (used to convert base velocity into momentum) */
+#define FL_WORLDBRUSH (1 << 24) /**< Not moveable/removeable brush entity (really part of the world, but represented as an entity for transparency or something) */
+#define FL_OBJECT (1 << 25) /**< Terrible name. This is an object that NPCs should see. Missiles, for example. */
+#define FL_KILLME (1 << 26) /**< This entity is marked for death -- will be freed by game DLL */
+#define FL_ONFIRE (1 << 27) /**< You know... */
+#define FL_DISSOLVING (1 << 28) /**< We're dissolving! */
+#define FL_TRANSRAGDOLL (1 << 29) /**< In the process of turning into a client side ragdoll. */
+#define FL_UNBLOCKABLE_BY_PLAYER (1 << 30) /**< pusher that can't be blocked by the player */
+#define FL_FREEZING (1 << 31) /**< We're becoming frozen! */
+#define FL_EP2V_UNKNOWN1 (1 << 31) /**< Unknown */
+// END entity flag #defines
+
+/**
+ * Get an entity's flags.
+ *
+ * @note The game's actual flags are internally translated by SM
+ * to match the entity flags defined above as the actual values
+ * can differ per engine.
+ *
+ * @param entity Entity index.
+ * @return Entity's flags, see entity flag defines above.
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+native GetEntityFlags(entity);
+
+/**
+ * Sets an entity's flags.
+ *
+ * @note The entity flags as defined above are internally translated by SM
+ * to match the current game's expected value for the flags as
+ * the actual values can differ per engine.
+ *
+ * @param entity Entity index.
+ * @param flags Entity flags, see entity flag defines above.
+ * @noreturn
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+native SetEntityFlags(entity, flags);
+
+
+/**
+ * Gets an entity's movetype.
+ *
+ * @param entity Entity index.
+ * @return Movetype, see enum above.
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+stock MoveType:GetEntityMoveType(entity)
+{
+ static bool:gotconfig = false;
+ static String:datamap[32];
+
+ if (!gotconfig)
+ {
+ new Handle:gc = LoadGameConfigFile("core.games");
+ new bool:exists = GameConfGetKeyValue(gc, "m_MoveType", datamap, sizeof(datamap));
+ CloseHandle(gc);
+
+ if (!exists)
+ {
+ strcopy(datamap, sizeof(datamap), "m_MoveType");
+ }
+
+ gotconfig = true;
+ }
+
+ return MoveType:GetEntProp(entity, Prop_Data, datamap);
+}
+
+/**
+ * Sets an entity's movetype.
+ *
+ * @param entity Entity index.
+ * @param mt Movetype, see enum above.
+ * @noreturn
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+stock SetEntityMoveType(entity, MoveType:mt)
+{
+ static bool:gotconfig = false;
+ static String:datamap[32];
+
+ if (!gotconfig)
+ {
+ new Handle:gc = LoadGameConfigFile("core.games");
+ new bool:exists = GameConfGetKeyValue(gc, "m_MoveType", datamap, sizeof(datamap));
+ CloseHandle(gc);
+
+ if (!exists)
+ {
+ strcopy(datamap, sizeof(datamap), "m_MoveType");
+ }
+
+ gotconfig = true;
+ }
+
+ SetEntProp(entity, Prop_Data, datamap, mt);
+}
+
+/**
+ * Gets an entity's render mode.
+ *
+ * @param entity Entity index.
+ * @return RenderMode value.
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+stock RenderMode:GetEntityRenderMode(entity)
+{
+ static bool:gotconfig = false;
+ static String:prop[32];
+
+ if (!gotconfig)
+ {
+ new Handle:gc = LoadGameConfigFile("core.games");
+ new bool:exists = GameConfGetKeyValue(gc, "m_nRenderMode", prop, sizeof(prop));
+ CloseHandle(gc);
+
+ if (!exists)
+ {
+ strcopy(prop, sizeof(prop), "m_nRenderMode");
+ }
+
+ gotconfig = true;
+ }
+
+ return RenderMode:GetEntProp(entity, Prop_Send, prop, 1);
+}
+
+/**
+ * Sets an entity's render mode.
+ *
+ * @param entity Entity index.
+ * @param mode RenderMode value.
+ * @noreturn
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+stock SetEntityRenderMode(entity, RenderMode:mode)
+{
+ static bool:gotconfig = false;
+ static String:prop[32];
+
+ if (!gotconfig)
+ {
+ new Handle:gc = LoadGameConfigFile("core.games");
+ new bool:exists = GameConfGetKeyValue(gc, "m_nRenderMode", prop, sizeof(prop));
+ CloseHandle(gc);
+
+ if (!exists)
+ {
+ strcopy(prop, sizeof(prop), "m_nRenderMode");
+ }
+
+ gotconfig = true;
+ }
+
+ SetEntProp(entity, Prop_Send, prop, mode, 1);
+}
+
+/**
+ * Gets an entity's render Fx.
+ *
+ * @param entity Entity index.
+ * @return RenderFx value.
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+stock RenderFx:GetEntityRenderFx(entity)
+{
+ static bool:gotconfig = false;
+ static String:prop[32];
+
+ if (!gotconfig)
+ {
+ new Handle:gc = LoadGameConfigFile("core.games");
+ new bool:exists = GameConfGetKeyValue(gc, "m_nRenderFX", prop, sizeof(prop));
+ CloseHandle(gc);
+
+ if (!exists)
+ {
+ strcopy(prop, sizeof(prop), "m_nRenderFX");
+ }
+
+ gotconfig = true;
+ }
+
+ return RenderFx:GetEntProp(entity, Prop_Send, prop, 1);
+}
+
+/**
+ * Sets an entity's render Fx.
+ *
+ * @param entity Entity index.
+ * @param fx RenderFx value.
+ * @noreturn
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+stock SetEntityRenderFx(entity, RenderFx:fx)
+{
+ static bool:gotconfig = false;
+ static String:prop[32];
+
+ if (!gotconfig)
+ {
+ new Handle:gc = LoadGameConfigFile("core.games");
+ new bool:exists = GameConfGetKeyValue(gc, "m_nRenderFX", prop, sizeof(prop));
+ CloseHandle(gc);
+
+ if (!exists)
+ {
+ strcopy(prop, sizeof(prop), "m_nRenderFX");
+ }
+
+ gotconfig = true;
+ }
+
+ SetEntProp(entity, Prop_Send, prop, fx, 1);
+}
+
+/**
+ * Sets an entity's color.
+ *
+ * @param entity Entity index
+ * @param r Amount of red (0-255)
+ * @param g Amount of green (0-255)
+ * @param b Amount of blue (0-255)
+ * @param a Amount of alpha (0-255)
+ * @noreturn
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+stock SetEntityRenderColor(entity, r=255, g=255, b=255, a=255)
+{
+ static bool:gotconfig = false;
+ static String:prop[32];
+
+ if (!gotconfig)
+ {
+ new Handle:gc = LoadGameConfigFile("core.games");
+ new bool:exists = GameConfGetKeyValue(gc, "m_clrRender", prop, sizeof(prop));
+ CloseHandle(gc);
+
+ if (!exists)
+ {
+ strcopy(prop, sizeof(prop), "m_clrRender");
+ }
+
+ gotconfig = true;
+ }
+
+ new offset = GetEntSendPropOffs(entity, prop);
+
+ if (offset <= 0)
+ {
+ ThrowError("SetEntityRenderColor not supported by this mod");
+ }
+
+ SetEntData(entity, offset, r, 1, true);
+ SetEntData(entity, offset + 1, g, 1, true);
+ SetEntData(entity, offset + 2, b, 1, true);
+ SetEntData(entity, offset + 3, a, 1, true);
+}
+
+/**
+ * Gets an entity's gravity.
+ *
+ * @param entity Entity index.
+ * @return Entity's m_flGravity value.
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+stock Float:GetEntityGravity(entity)
+{
+ static bool:gotconfig = false;
+ static String:datamap[32];
+
+ if (!gotconfig)
+ {
+ new Handle:gc = LoadGameConfigFile("core.games");
+ new bool:exists = GameConfGetKeyValue(gc, "m_flGravity", datamap, sizeof(datamap));
+ CloseHandle(gc);
+
+ if (!exists)
+ {
+ strcopy(datamap, sizeof(datamap), "m_flGravity");
+ }
+
+ gotconfig = true;
+ }
+
+ return GetEntPropFloat(entity, Prop_Data, datamap);
+}
+
+/**
+ * Sets an entity's gravity.
+ *
+ * @param entity Entity index.
+ * @param amount Gravity to set (default = 1.0, half = 0.5, double = 2.0).
+ * @noreturn
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+stock SetEntityGravity(entity, Float:amount)
+{
+ static bool:gotconfig = false;
+ static String:datamap[32];
+
+ if (!gotconfig)
+ {
+ new Handle:gc = LoadGameConfigFile("core.games");
+ new bool:exists = GameConfGetKeyValue(gc, "m_flGravity", datamap, sizeof(datamap));
+ CloseHandle(gc);
+
+ if (!exists)
+ {
+ strcopy(datamap, sizeof(datamap), "m_flGravity");
+ }
+
+ gotconfig = true;
+ }
+
+ SetEntPropFloat(entity, Prop_Data, datamap, amount);
+}
+
+/**
+ * Sets an entity's health
+ *
+ * @param entity Entity index.
+ * @param amount Health amount.
+ * @noreturn
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+stock SetEntityHealth(entity, amount)
+{
+ static bool:gotconfig = false;
+ static String:prop[32];
+
+ if (!gotconfig)
+ {
+ new Handle:gc = LoadGameConfigFile("core.games");
+ new bool:exists = GameConfGetKeyValue(gc, "m_iHealth", prop, sizeof(prop));
+ CloseHandle(gc);
+
+ if (!exists)
+ {
+ strcopy(prop, sizeof(prop), "m_iHealth");
+ }
+
+ gotconfig = true;
+ }
+
+ decl String:cls[64];
+ new PropFieldType:type;
+ new offset;
+
+ if (!GetEntityNetClass(entity, cls, sizeof(cls)))
+ {
+ ThrowError("SetEntityHealth not supported by this mod: Could not get serverclass name");
+ return;
+ }
+
+ offset = FindSendPropInfo(cls, prop, type);
+
+ if (offset <= 0)
+ {
+ ThrowError("SetEntityHealth not supported by this mod");
+ return;
+ }
+
+ /* Dark Messiah uses a float for the health instead an integer */
+ if (type == PropField_Float)
+ {
+ SetEntDataFloat(entity, offset, float(amount));
+ }
+ else
+ {
+ SetEntProp(entity, Prop_Send, prop, amount);
+ }
+}
+
+/**
+ * Get's a users current pressed buttons
+ *
+ * @param client Client index
+ * @return Bitsum of buttons
+ * @error Invalid client index, client not in game,
+ * or lack of mod compliance.
+ */
+stock GetClientButtons(client)
+{
+ static bool:gotconfig = false;
+ static String:datamap[32];
+
+ if (!gotconfig)
+ {
+ new Handle:gc = LoadGameConfigFile("core.games");
+ new bool:exists = GameConfGetKeyValue(gc, "m_nButtons", datamap, sizeof(datamap));
+ CloseHandle(gc);
+
+ if (!exists)
+ {
+ strcopy(datamap, sizeof(datamap), "m_nButtons");
+ }
+
+ gotconfig = true;
+ }
+
+ return GetEntProp(client, Prop_Data, datamap);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/events.inc b/sourcemod-1.5-dev/scripting/include/events.inc
new file mode 100644
index 0000000..d7e8f4c
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/events.inc
@@ -0,0 +1,257 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _events_included
+ #endinput
+#endif
+#define _events_included
+
+/**
+ * Event hook modes determining how hooking should be handled
+ */
+enum EventHookMode
+{
+ EventHookMode_Pre, /**< Hook callback fired before event is fired */
+ EventHookMode_Post, /**< Hook callback fired after event is fired */
+ EventHookMode_PostNoCopy /**< Hook callback fired after event is fired, but event data won't be copied */
+};
+
+/**
+ * Hook function types for events.
+ */
+funcenum EventHook
+{
+ /**
+ * Called when a game event is fired.
+ *
+ * @param event Handle to event. This could be INVALID_HANDLE if every plugin hooking
+ * this event has set the hook mode EventHookMode_PostNoCopy.
+ * @param name String containing the name of the event.
+ * @param dontBroadcast True if event was not broadcast to clients, false otherwise.
+ * @return Ignored for post hooks. Plugin_Handled will block event if hooked as pre.
+ */
+ Action:public(Handle:event, const String:name[], bool:dontBroadcast),
+ /**
+ * Called when a game event is fired.
+ *
+ * @param event Handle to event. This could be INVALID_HANDLE if every plugin hooking
+ * this event has set the hook mode EventHookMode_PostNoCopy.
+ * @param name String containing the name of the event.
+ * @param dontBroadcast True if event was not broadcast to clients, false otherwise.
+ * @noreturn
+ */
+ public(Handle:event, const String:name[], bool:dontBroadcast),
+};
+
+/**
+ * Creates a hook for when a game event is fired.
+ *
+ * @param name Name of event.
+ * @param callback An EventHook function pointer.
+ * @param mode Optional EventHookMode determining the type of hook.
+ * @noreturn
+ * @error Invalid event name or invalid callback function.
+ */
+native HookEvent(const String:name[], EventHook:callback, EventHookMode:mode=EventHookMode_Post);
+
+/**
+ * Creates a hook for when a game event is fired.
+ *
+ * @param name Name of event.
+ * @param callback An EventHook function pointer.
+ * @param mode Optional EventHookMode determining the type of hook.
+ * @return True if event exists and was hooked successfully, false otherwise.
+ * @error Invalid callback function.
+ */
+native bool:HookEventEx(const String:name[], EventHook:callback, EventHookMode:mode=EventHookMode_Post);
+
+/**
+ * Removes a hook for when a game event is fired.
+ *
+ * @param name Name of event.
+ * @param callback An EventHook function pointer.
+ * @param mode Optional EventHookMode determining the type of hook.
+ * @noreturn
+ * @error Invalid callback function or no active hook for specified event.
+ */
+native UnhookEvent(const String:name[], EventHook:callback, EventHookMode:mode=EventHookMode_Post);
+
+/**
+ * Creates a game event to be fired later.
+ *
+ * The Handle should not be closed via CloseHandle(). It must be closed via
+ * FireEvent() or CancelCreatedEvent().
+ *
+ * @param name Name of event.
+ * @param force If set to true, this forces the event to be created even if it's not being hooked.
+ * Note that this will not force it if the event doesn't exist at all.
+ * @return Handle to event. INVALID_HANDLE is returned if the event doesn't exist or isn't
+ being hooked (unless force is true).
+ */
+native Handle:CreateEvent(const String:name[], bool:force=false);
+
+/**
+ * Fires a game event.
+ *
+ * This function closes the event Handle after completing.
+ *
+ * @param event Handle to the event.
+ * @param dontBroadcast Optional boolean that determines if event should be broadcast to clients.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native FireEvent(Handle:event, bool:dontBroadcast=false);
+
+/**
+ * Cancels a previously created game event that has not been fired.
+ *
+ * @param event Handled to the event.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native CancelCreatedEvent(Handle:event);
+
+/**
+ * Returns the boolean value of a game event's key.
+ *
+ * @param event Handle to the event.
+ * @param key Name of event key.
+ * @return The boolean value of the specfied event key.
+ * @error Invalid or corrupt Handle.
+ */
+native bool:GetEventBool(Handle:event, const String:key[]);
+
+/**
+ * Sets the boolean value of a game event's key.
+ *
+ * @param event Handle to the event.
+ * @param key Name of event key.
+ * @param value New boolean value.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native SetEventBool(Handle:event, const String:key[], bool:value);
+
+/**
+ * Returns the integer value of a game event's key.
+ *
+ * @param event Handle to the event.
+ * @param key Name of event key.
+ * @return The integer value of the specfied event key.
+ * @error Invalid or corrupt Handle.
+ */
+native GetEventInt(Handle:event, const String:key[]);
+
+/**
+ * Sets the integer value of a game event's key.
+ *
+ * Integer value refers to anything that can be reduced to an integer.
+ * The various size specifiers, such as "byte" and "short" are still
+ * integers, and only refer to how much data will actually be sent
+ * over the network (if applicable).
+ *
+ * @param event Handle to the event.
+ * @param key Name of event key.
+ * @param value New integer value.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native SetEventInt(Handle:event, const String:key[], value);
+
+/**
+ * Returns the floating point value of a game event's key.
+ *
+ * @param event Handle to the event.
+ * @param key Name of event key.
+ * @return The floating point value of the specfied event key.
+ * @error Invalid or corrupt Handle.
+ */
+native Float:GetEventFloat(Handle:event, const String:key[]);
+
+/**
+ * Sets the floating point value of a game event's key.
+ *
+ * @param event Handle to the event.
+ * @param key Name of event key.
+ * @param value New floating point value.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native SetEventFloat(Handle:event, const String:key[], Float:value);
+
+/**
+ * Retrieves the string value of a game event's key.
+ *
+ * @param event Handle to the event.
+ * @param key Name of event key.
+ * @param value Buffer to store the value of the specified event key.
+ * @param maxlength Maximum length of string buffer.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native GetEventString(Handle:event, const String:key[], String:value[], maxlength);
+
+/**
+ * Sets the string value of a game event's key.
+ *
+ * @param event Handle to the event.
+ * @param key Name of event key.
+ * @param value New string value.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native SetEventString(Handle:event, const String:key[], const String:value[]);
+
+/**
+ * Retrieves the name of a game event.
+ *
+ * @param event Handle to the event.
+ * @param name Buffer to store the name of the event.
+ * @param maxlength Maximum length of string buffer.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native GetEventName(Handle:event, String:name[], maxlength);
+
+/**
+ * Sets whether an event's broadcasting will be disabled or not.
+ *
+ * This has no effect on events Handles that are not from HookEvent
+ * or HookEventEx callbacks.
+ *
+ * @param event Handle to an event from an event hook.
+ * @param dontBroadcast True to disable broadcasting, false otherwise.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native SetEventBroadcast(Handle:event, bool:dontBroadcast);
+
diff --git a/sourcemod-1.5-dev/scripting/include/files.inc b/sourcemod-1.5-dev/scripting/include/files.inc
new file mode 100644
index 0000000..f353deb
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/files.inc
@@ -0,0 +1,411 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _files_included
+ #endinput
+#endif
+#define _files_included
+
+/**
+ * @global All paths in SourceMod natives are relative to the mod folder
+ * unless otherwise noted.
+ *
+ * Most functions in SourceMod (at least, ones that deal with direct
+ * file manipulation) will support an alternate path specification.
+ *
+ * If the path starts with the string "file://" and the PathType is
+ * not relative, then the "file://" portion is stripped off, and the
+ * rest of the path is used without any modification (except for
+ * correcting slashes). This can be used to override the path
+ * builder to supply alternate absolute paths. Examples:
+ *
+ * file://C:/Temp/file.txt
+ * file:///tmp/file.txt
+ */
+
+/**
+ * File inode types.
+ */
+enum FileType
+{
+ FileType_Unknown = 0, /* Unknown file type (device/socket) */
+ FileType_Directory = 1, /* File is a directory */
+ FileType_File = 2, /* File is a file */
+};
+
+/**
+ * File time modes.
+ */
+enum FileTimeMode
+{
+ FileTime_LastAccess = 0, /* Last access (does not work on FAT) */
+ FileTime_Created = 1, /* Creation (does not work on FAT) */
+ FileTime_LastChange = 2, /* Last modification */
+};
+
+#define PLATFORM_MAX_PATH 256 /**< Maximum path length. */
+
+#define SEEK_SET 0 /**< Seek from start. */
+#define SEEK_CUR 1 /**< Seek from current position. */
+#define SEEK_END 2 /**< Seek from end position. */
+
+/**
+ * Path types.
+ */
+enum PathType
+{
+ Path_SM, /**< SourceMod root folder */
+};
+
+/**
+ * Builds a path relative to the SourceMod folder. This should be used instead of
+ * directly referencing addons/sourcemod, in case users change the name of their
+ * folder layout.
+ *
+ * @param type Type of path to build as the base.
+ * @param buffer Buffer to store the path.
+ * @param maxlength Maximum length of buffer.
+ * @param fmt Format string.
+ * @param ... Format arguments.
+ * @return Number of bytes written to buffer (not including null terminator).
+ */
+native BuildPath(PathType:type, String:buffer[], maxlength, const String:fmt[], any:...);
+
+/**
+ * Opens a directory/folder for contents enumeration.
+ *
+ * @note Directories are closed with CloseHandle().
+ * @note Directories Handles can be cloned.
+ * @note OpenDirectory() supports the "file://" notation.
+ *
+ * @param path Path to open.
+ * @return A Handle to the directory, INVALID_HANDLE on open error.
+ */
+native Handle:OpenDirectory(const String:path[]);
+
+/**
+ * Reads the current directory entry as a local filename, then moves to the next file.
+ *
+ * @note Contents of buffers are undefined when returning false.
+ * @note Both the '.' and '..' automatic directory entries will be retrieved for Windows and Linux.
+ *
+ * @param dir Handle to a directory.
+ * @param buffer String buffer to hold directory name.
+ * @param maxlength Maximum size of string buffer.
+ * @param type Optional variable to store the file type.
+ * @return True on success, false if there are no more files to read.
+ * @error Invalid or corrupt Handle.
+ */
+native bool:ReadDirEntry(Handle:dir, String:buffer[], maxlength, &FileType:type=FileType_Unknown);
+
+/**
+ * Opens a file.
+ *
+ * @note Files are closed with CloseHandle().
+ * @note File Handles can be cloned.
+ * @note OpenFile() supports the "file://" notation.
+ *
+ * @param file File to open.
+ * @param mode Open mode.
+ * @return A Handle to the file, INVALID_HANDLE on open error.
+ */
+native Handle:OpenFile(const String:file[], const String:mode[]);
+
+/**
+ * Deletes a file.
+ *
+ * @param path Path of the file to delete.
+ * @return True on success, false otherwise.
+ */
+native bool:DeleteFile(const String:path[]);
+
+/**
+ * Reads a line from a text file.
+ *
+ * @param hndl Handle to the file.
+ * @param buffer String buffer to hold the line.
+ * @param maxlength Maximum size of string buffer.
+ * @return True on success, false otherwise.
+ */
+native bool:ReadFileLine(Handle:hndl, String:buffer[], maxlength);
+
+/**
+ * Reads binary data from a file.
+ *
+ * @param hndl Handle to the file.
+ * @param items Array to store each item read.
+ * @param num_items Number of items to read into the array.
+ * @param size Size of each element, in bytes, to be read.
+ * Valid sizes are 1, 2, or 4.
+ * @return Number of elements read, or -1 on error.
+ */
+native ReadFile(Handle:hndl, items[], num_items, size);
+
+/**
+ * Reads a UTF8 or ANSI string from a file.
+ *
+ * @param hndl Handle to the file.
+ * @param buffer Buffer to store the string.
+ * @param max_size Maximum size of the string buffer.
+ * @param read_count If -1, reads until a null terminator is encountered in
+ * the file. Otherwise, read_count bytes are read
+ * into the buffer provided. In this case the buffer
+ * is not explicitly null terminated, and the buffer
+ * will contain any null terminators read from the file.
+ * @return Number of characters written to the buffer, or -1
+ * if an error was encountered.
+ * @error Invalid Handle, or read_count > max_size.
+ */
+native ReadFileString(Handle:hndl, String:buffer[], max_size, read_count=-1);
+
+/**
+ * Writes binary data to a file.
+ *
+ * @param hndl Handle to the file.
+ * @param items Array of items to write. The data is read directly.
+ * That is, in 1 or 2-byte mode, the lower byte(s) in
+ * each cell are used directly, rather than performing
+ * any casts from a 4-byte number to a smaller number.
+ * @param num_items Number of items in the array.
+ * @param size Size of each item in the array in bytes.
+ * Valid sizes are 1, 2, or 4.
+ * @return True on success, false on error.
+ * @error Invalid Handle.
+ */
+native bool:WriteFile(Handle:hndl, const items[], num_items, size);
+
+/**
+ * Writes a binary string to a file.
+ *
+ * @param hndl Handle to th efile.
+ * @param buffer String to write.
+ * @param term True to append NUL terminator, false otherwise.
+ * @return True on success, false on error.
+ * @error Invalid Handle.
+ */
+native bool:WriteFileString(Handle:hndl, const String:buffer[], bool:term);
+
+/**
+ * Writes a line of text to a text file. A newline is automatically appended.
+ *
+ * @param hndl Handle to the file.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @return True on success, false otherwise.
+ * @error Invalid Handle.
+ */
+native bool:WriteFileLine(Handle:hndl, const String:format[], any:...);
+
+/**
+ * Reads a single binary cell from a file.
+ *
+ * @param hndl Handle to the file.
+ * @param data Variable to store the data read.
+ * @param size Size of the data to read in bytes. Valid
+ * sizes are 1, 2, or 4 bytes.
+ * @return Number of elements read (max 1), or -1 on error.
+ * @error Invalid Handle.
+ */
+stock ReadFileCell(Handle:hndl, &data, size)
+{
+ new array[1], ret;
+
+ if ((ret = ReadFile(hndl, array, 1, size)) == 1)
+ {
+ data = array[0];
+ }
+
+ return ret;
+}
+
+/**
+ * Writes a single binary cell to a file.
+ *
+ * @param hndl Handle to the file.
+ * @param data Cell to write to the file.
+ * @param size Size of the data to read in bytes. Valid
+ * sizes are 1, 2, or 4 bytes. If the size
+ * is less than 4 bytes, the data is truncated
+ * rather than casted. That is, only the lower
+ * bits will be read.
+ * @return True on success, false on error.
+ * @error Invalid Handle.
+ */
+stock bool:WriteFileCell(Handle:hndl, data, size)
+{
+ new array[1];
+
+ array[0] = data;
+
+ return WriteFile(hndl, array, 1, size);
+}
+
+/**
+ * Tests if the end of file has been reached.
+ *
+ * @param file Handle to the file.
+ * @return True if end of file has been reached, false otherwise.
+ * @error Invalid Handle.
+ */
+native bool:IsEndOfFile(Handle:file);
+
+/**
+ * Sets the file position indicator.
+ *
+ * @param file Handle to the file.
+ * @param position Position relative to what is specified in whence.
+ * @param where SEEK_ constant value of where to see from.
+ * @return True on success, false otherwise.
+ * @error Invalid Handle.
+ */
+native bool:FileSeek(Handle:file, position, where);
+
+/**
+ * Get current position in the file.
+ *
+ * @param file Handle to the file.
+ * @return Value for the file position indicator.
+ * @error Invalid Handle.
+ */
+native FilePosition(Handle:file);
+
+/**
+ * Checks if a file exists.
+ *
+ * @param path Path to the file.
+ * @param use_valve_fs If true, the Valve file system will be used instead.
+ * This can be used to find files existing in any of
+ * the GAME search paths, rather than solely files
+ * existing directly in the gamedir.
+ * @return True if the file exists, false otherwise.
+ */
+native bool:FileExists(const String:path[], bool:use_valve_fs=false);
+
+/**
+ * Renames a file.
+ *
+ * @param newpath New path to the file.
+ * @param oldpath Path to the existing file.
+ * @return True on success, false otherwise.
+ */
+native bool:RenameFile(const String:newpath[], const String:oldpath[]);
+
+/**
+ * Checks if a directory exists.
+ *
+ * @param path Path to the directory.
+ * @return True if the directory exists, false otherwise.
+ */
+native bool:DirExists(const String:path[]);
+
+/**
+ * Get the file size in bytes.
+ *
+ * @param path Path to the file.
+ * @param use_valve_fs If true, the Valve file system will be used instead.
+ * This can be used to find files existing in any of
+ * the GAME search paths, rather than solely files
+ * existing directly in the gamedir.
+ * @return File size in bytes, -1 if file not found.
+ */
+native FileSize(const String:path[], bool:use_valve_fs=false);
+
+/**
+ * Flushes a file's buffered output; any buffered output
+ * is immediately written to the file.
+ *
+ * @param file Handle to the file.
+ * @return True on success, false on failure.
+ */
+native FlushFile(Handle:file);
+
+/**
+ * Removes a directory.
+ * @note On most Operating Systems you cannot remove a directory which has files inside it.
+ *
+ * @param path Path to the directory.
+ * @return True on success, false otherwise.
+ */
+native bool:RemoveDir(const String:path[]);
+
+#define FPERM_U_READ 0x0100 /* User can read. */
+#define FPERM_U_WRITE 0x0080 /* User can write. */
+#define FPERM_U_EXEC 0x0040 /* User can exec. */
+#define FPERM_G_READ 0x0020 /* Group can read. */
+#define FPERM_G_WRITE 0x0010 /* Group can write. */
+#define FPERM_G_EXEC 0x0008 /* Group can exec. */
+#define FPERM_O_READ 0x0004 /* Anyone can read. */
+#define FPERM_O_WRITE 0x0002 /* Anyone can write. */
+#define FPERM_O_EXEC 0x0001 /* Anyone can exec. */
+
+/**
+ * Creates a directory.
+ *
+ * @param path Path to create.
+ * @param mode Permissions (default is o=rx,g=rx,u=rwx). Note that folders must have
+ * the execute bit set on Linux. On Windows, the mode is ignored.
+ */
+native bool:CreateDirectory(const String:path[], mode);
+
+/**
+ * Returns a file timestamp as a unix timestamp.
+ *
+ * @param file File name.
+ * @param tmode Time mode.
+ * @return Time value, or -1 on failure.
+ */
+native GetFileTime(const String:file[], FileTimeMode:tmode);
+
+/**
+ * Same as LogToFile(), except uses an open file Handle. The file must
+ * be opened in text appending mode.
+ *
+ * @param hndl Handle to the file.
+ * @param message Message format.
+ * @param ... Message format parameters.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native LogToOpenFile(Handle:hndl, const String:message[], any:...);
+
+/**
+ * Same as LogToFileEx(), except uses an open file Handle. The file must
+ * be opened in text appending mode.
+ *
+ * @param hndl Handle to the file.
+ * @param message Message format.
+ * @param ... Message format parameters.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native LogToOpenFileEx(Handle:hndl, const String:message[], any:...);
+
diff --git a/sourcemod-1.5-dev/scripting/include/float.inc b/sourcemod-1.5-dev/scripting/include/float.inc
new file mode 100644
index 0000000..1282158
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/float.inc
@@ -0,0 +1,437 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _float_included
+ #endinput
+#endif
+#define _float_included
+
+/**
+ * Converts an integer into a floating point value.
+ *
+ * @param value Integer to convert.
+ * @return Floating point value.
+ */
+native Float:float(value);
+
+/**
+ * Multiplies two floats together.
+ *
+ * @param oper1 First value.
+ * @param oper2 Second value.
+ * @return oper1*oper2.
+ */
+native Float:FloatMul(Float:oper1, Float:oper2);
+
+/**
+ * Divides the dividend by the divisor.
+ *
+ * @param dividend First value.
+ * @param divisor Second value.
+ * @return dividend/divisor.
+ */
+native Float:FloatDiv(Float:dividend, Float:divisor);
+
+/**
+ * Adds two floats together.
+ *
+ * @param oper1 First value.
+ * @param oper2 Second value.
+ * @return oper1+oper2.
+ */
+native Float:FloatAdd(Float:oper1, Float:oper2);
+
+/**
+ * Subtracts oper2 from oper1.
+ *
+ * @param oper1 First value.
+ * @param oper2 Second value.
+ * @return oper1-oper2.
+ */
+native Float:FloatSub(Float:oper1, Float:oper2);
+
+/**
+ * Returns the decimal part of a float.
+ *
+ * @param value Input value.
+ * @return Decimal part.
+ */
+native Float:FloatFraction(Float:value);
+
+/**
+ * Rounds a float to the closest integer to zero.
+ *
+ * @param value Input value to be rounded.
+ * @return Rounded value.
+ */
+native RoundToZero(Float:value);
+
+/**
+ * Rounds a float to the next highest integer value.
+ *
+ * @param value Input value to be rounded.
+ * @return Rounded value.
+ */
+native RoundToCeil(Float:value);
+
+/**
+ * Rounds a float to the next lowest integer value.
+ *
+ * @param value Input value to be rounded.
+ * @return Rounded value.
+ */
+native RoundToFloor(Float:value);
+
+/**
+ * Standard IEEE rounding.
+ *
+ * @param value Input value to be rounded.
+ * @return Rounded value.
+ */
+native RoundToNearest(Float:value);
+
+/**
+ * Compares two floats.
+ *
+ * @param fOne First value.
+ * @param fTwo Second value.
+ * @return Returns 1 if the first argument is greater than the second argument.
+ * Returns -1 if the first argument is smaller than the second argument.
+ * Returns 0 if both arguments are equal.
+ */
+native FloatCompare(Float:fOne, Float:fTwo);
+
+/**
+ * Returns the square root of the input value, equivalent to floatpower(value, 0.5).
+ *
+ * @param value Input value.
+ * @return Square root of the value.
+ */
+native Float:SquareRoot(Float:value);
+
+/**
+ * Returns the value raised to the power of the exponent.
+ *
+ * @param value Value to be raised.
+ * @param exponent Value to raise the base.
+ * @return value^exponent.
+ */
+native Float:Pow(Float:value, Float:exponent);
+
+/**
+ * Returns the value of raising the input by e.
+ *
+ * @param value Input value.
+ * @return exp(value).
+ */
+native Float:Exponential(Float:value);
+
+/**
+ * Returns the logarithm of any base specified.
+ *
+ * @param value Input value.
+ * @param base Logarithm base to use, default is 10.
+ * @return log(value)/log(base).
+ */
+native Float:Logarithm(Float:value, Float:base=10.0);
+
+/**
+ * Returns the sine of the argument.
+ *
+ * @param value Input value in radians.
+ * @return sin(value).
+ */
+native Float:Sine(Float:value);
+
+/**
+ * Returns the cosine of the argument.
+ *
+ * @param value Input value in radians.
+ * @return cos(value).
+ */
+native Float:Cosine(Float:value);
+
+/**
+ * Returns the tangent of the argument.
+ *
+ * @param value Input value in radians.
+ * @return tan(value).
+ */
+native Float:Tangent(Float:value);
+
+/**
+ * Returns an absolute value.
+ *
+ * @param value Input value.
+ * @return Absolute value of the input.
+ */
+native Float:FloatAbs(Float:value);
+
+/**
+ * Returns the arctangent of the input value.
+ *
+ * @param angle Input value.
+ * @return atan(value) in radians.
+ */
+native Float:ArcTangent(Float:angle);
+
+/**
+ * Returns the arccosine of the input value.
+ *
+ * @param angle Input value.
+ * @return acos(value) in radians.
+ */
+native Float:ArcCosine(Float:angle);
+
+/**
+ * Returns the arcsine of the input value.
+ *
+ * @param angle Input value.
+ * @return asin(value) in radians.
+ */
+native Float:ArcSine(Float:angle);
+
+/**
+ * Returns the arctangent2 of the input values.
+ *
+ * @param x Horizontal value.
+ * @param y Vertical value.
+ * @return atan2(value) in radians.
+ */
+native Float:ArcTangent2(Float:x, Float:y);
+
+/**
+ * Rounds a floating point number using the "round to nearest" algorithm.
+ *
+ * @param value Floating point value to round.
+ * @return The value rounded to the nearest integer.
+ */
+stock RoundFloat(Float:value)
+{
+ return RoundToNearest(value);
+}
+
+/**
+ * User defined operators.
+ *
+ */
+#pragma rational Float
+
+native bool:__FLOAT_GT__(Float:a, Float:b);
+native bool:__FLOAT_GE__(Float:a, Float:b);
+native bool:__FLOAT_LT__(Float:a, Float:b);
+native bool:__FLOAT_LE__(Float:a, Float:b);
+native bool:__FLOAT_EQ__(Float:a, Float:b);
+native bool:__FLOAT_NE__(Float:a, Float:b);
+native bool:__FLOAT_NOT__(Float:a);
+
+native Float:operator*(Float:oper1, Float:oper2) = FloatMul;
+native Float:operator/(Float:oper1, Float:oper2) = FloatDiv;
+native Float:operator+(Float:oper1, Float:oper2) = FloatAdd;
+native Float:operator-(Float:oper1, Float:oper2) = FloatSub;
+native bool:operator!(Float:oper1) = __FLOAT_NOT__;
+native bool:operator>(Float:oper1, Float:oper2) = __FLOAT_GT__;
+native bool:operator>=(Float:oper1, Float:oper2) = __FLOAT_GE__;
+native bool:operator<(Float:oper1, Float:oper2) = __FLOAT_LT__;
+native bool:operator<=(Float:oper1, Float:oper2) = __FLOAT_LE__;
+native bool:operator!=(Float:oper1, Float:oper2) = __FLOAT_NE__;
+native bool:operator==(Float:oper1, Float:oper2) = __FLOAT_EQ__;
+
+stock Float:operator++(Float:oper)
+{
+ return oper+1.0;
+}
+
+stock Float:operator--(Float:oper)
+{
+ return oper-1.0;
+}
+
+stock Float:operator-(Float:oper)
+{
+ return oper^Float:cellmin; /* IEEE values are sign/magnitude */
+}
+
+stock Float:operator*(Float:oper1, oper2)
+{
+ return FloatMul(oper1, float(oper2)); /* "*" is commutative */
+}
+
+stock Float:operator/(Float:oper1, oper2)
+{
+ return FloatDiv(oper1, float(oper2));
+}
+
+stock Float:operator/(oper1, Float:oper2)
+{
+ return FloatDiv(float(oper1), oper2);
+}
+
+stock Float:operator+(Float:oper1, oper2)
+{
+ return FloatAdd(oper1, float(oper2)); /* "+" is commutative */
+}
+
+stock Float:operator-(Float:oper1, oper2)
+{
+ return FloatSub(oper1, float(oper2));
+}
+
+stock Float:operator-(oper1, Float:oper2)
+{
+ return FloatSub(float(oper1), oper2);
+}
+
+stock bool:operator==(Float:oper1, oper2)
+{
+ return __FLOAT_EQ__(oper1, float(oper2));
+}
+
+stock bool:operator!=(Float:oper1, oper2)
+{
+ return __FLOAT_NE__(oper1, float(oper2));
+}
+
+stock bool:operator>(Float:oper1, oper2)
+{
+ return __FLOAT_GT__(oper1, float(oper2));
+}
+
+stock bool:operator>(oper1, Float:oper2)
+{
+ return __FLOAT_GT__(float(oper1), oper2);
+}
+
+stock bool:operator>=(Float:oper1, oper2)
+{
+ return __FLOAT_GE__(oper1, float(oper2));
+}
+
+stock bool:operator>=(oper1, Float:oper2)
+{
+ return __FLOAT_GE__(float(oper1), oper2);
+}
+
+stock bool:operator<(Float:oper1, oper2)
+{
+ return __FLOAT_LT__(oper1, float(oper2));
+}
+
+stock bool:operator<(oper1, Float:oper2)
+{
+ return __FLOAT_LT__(float(oper1), oper2);
+}
+
+stock bool:operator<=(Float:oper1, oper2)
+{
+ return __FLOAT_LE__(oper1, float(oper2));
+}
+
+stock bool:operator<=(oper1, Float:oper2)
+{
+ return __FLOAT_LE__(float(oper1), oper2);
+}
+
+/**
+ * Forbidden operators.
+ *
+ */
+forward operator%(Float:oper1, Float:oper2);
+forward operator%(Float:oper1, oper2);
+forward operator%(oper1, Float:oper2);
+
+#define FLOAT_PI 3.1415926535897932384626433832795
+
+/**
+ * Converts degrees to radians.
+ *
+ * @param angle Degrees.
+ * @return Radians.
+ */
+stock Float:DegToRad(Float:angle)
+{
+ return (angle*FLOAT_PI)/180;
+}
+
+/**
+ * Converts degrees to radians.
+ *
+ * @param angle Radians.
+ * @return Degrees.
+ */
+stock Float:RadToDeg(Float:angle)
+{
+ return (angle*180)/FLOAT_PI;
+}
+
+/**
+ * Returns a random integer in the range [0, 2^31-1].
+ *
+ * Note: Uniform random number streams are seeded automatically per-plugin.
+ *
+ * @return Random integer.
+ */
+native GetURandomInt();
+
+/**
+ * Returns a uniform random float in the range [0, 1).
+ *
+ * Note: Uniform random number streams are seeded automatically per-plugin.
+ *
+ * @return Uniform random floating-point number.
+ */
+native Float:GetURandomFloat();
+
+/**
+ * Seeds a plugin's uniform random number stream. This is done automatically,
+ * so normally it is totally unnecessary to call this.
+ *
+ * @param seeds Array of numbers to use as seeding data.
+ * @param numSeeds Number of seeds in the seeds array.
+ * @noreturn
+ */
+native SetURandomSeed(const seeds[], numSeeds);
+
+/**
+ * Seeds a plugin's uniform random number stream. This is done automatically,
+ * so normally it is totally unnecessary to call this.
+ *
+ * @param seed Single seed value.
+ * @noreturn
+ */
+stock SetURandomSeedSimple(seed)
+{
+ new seeds[1];
+ seeds[0] = seed;
+ SetURandomSeed(seeds, 1);
+}
+
diff --git a/sourcemod-1.5-dev/scripting/include/functions.inc b/sourcemod-1.5-dev/scripting/include/functions.inc
new file mode 100644
index 0000000..105f1d2
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/functions.inc
@@ -0,0 +1,511 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _functions_included
+ #endinput
+#endif
+#define _functions_included
+
+#define SP_PARAMFLAG_BYREF (1<<0) /**< Internal use only. */
+
+/**
+ * Describes the various ways to pass parameters to functions or forwards.
+ */
+enum ParamType
+{
+ Param_Any = 0, /**< Any data type can be pushed */
+ Param_Cell = (1<<1), /**< Only basic cells can be pushed */
+ Param_Float = (2<<1), /**< Only floats can be pushed */
+ Param_String = (3<<1)|SP_PARAMFLAG_BYREF, /**< Only strings can be pushed */
+ Param_Array = (4<<1)|SP_PARAMFLAG_BYREF, /**< Only arrays can be pushed */
+ Param_VarArgs = (5<<1), /**< Same as "..." in plugins, anything can be pushed, but it will always be byref */
+ Param_CellByRef = (1<<1)|SP_PARAMFLAG_BYREF, /**< Only a cell by reference can be pushed */
+ Param_FloatByRef = (2<<1)|SP_PARAMFLAG_BYREF /**< Only a float by reference can be pushed */
+};
+
+/**
+ * Defines how a forward iterates through plugin functions.
+ */
+enum ExecType
+{
+ ET_Ignore = 0, /**< Ignore all return values, return 0 */
+ ET_Single = 1, /**< Only return the last exec, ignore all others */
+ ET_Event = 2, /**< Acts as an event with the Actions defined in core.inc, no mid-Stops allowed, returns highest */
+ ET_Hook = 3 /**< Acts as a hook with the Actions defined in core.inc, mid-Stops allowed, returns highest */
+};
+
+/**
+ * @section Flags that are used with Call_PushArrayEx() and Call_PushStringEx()
+ */
+
+#define SM_PARAM_COPYBACK (1<<0) /**< Copy an array/reference back after call */
+
+#define SM_PARAM_STRING_UTF8 (1<<0) /**< String should be UTF-8 handled */
+#define SM_PARAM_STRING_COPY (1<<1) /**< String should be copied into the plugin */
+#define SM_PARAM_STRING_BINARY (1<<2) /**< Treat the string as a binary string */
+
+/**
+ * @endsection
+ */
+
+/**
+ * @section Error codes
+ */
+#define SP_ERROR_NONE 0 /**< No error occurred */
+#define SP_ERROR_FILE_FORMAT 1 /**< File format unrecognized */
+#define SP_ERROR_DECOMPRESSOR 2 /**< A decompressor was not found */
+#define SP_ERROR_HEAPLOW 3 /**< Not enough space left on the heap */
+#define SP_ERROR_PARAM 4 /**< Invalid parameter or parameter type */
+#define SP_ERROR_INVALID_ADDRESS 5 /**< A memory address was not valid */
+#define SP_ERROR_NOT_FOUND 6 /**< The object in question was not found */
+#define SP_ERROR_INDEX 7 /**< Invalid index parameter */
+#define SP_ERROR_STACKLOW 8 /**< Nnot enough space left on the stack */
+#define SP_ERROR_NOTDEBUGGING 9 /**< Debug mode was not on or debug section not found */
+#define SP_ERROR_INVALID_INSTRUCTION 10 /**< Invalid instruction was encountered */
+#define SP_ERROR_MEMACCESS 11 /**< Invalid memory access */
+#define SP_ERROR_STACKMIN 12 /**< Stack went beyond its minimum value */
+#define SP_ERROR_HEAPMIN 13 /**< Heap went beyond its minimum value */
+#define SP_ERROR_DIVIDE_BY_ZERO 14 /**< Division by zero */
+#define SP_ERROR_ARRAY_BOUNDS 15 /**< Array index is out of bounds */
+#define SP_ERROR_INSTRUCTION_PARAM 16 /**< Instruction had an invalid parameter */
+#define SP_ERROR_STACKLEAK 17 /**< A native leaked an item on the stack */
+#define SP_ERROR_HEAPLEAK 18 /**< A native leaked an item on the heap */
+#define SP_ERROR_ARRAY_TOO_BIG 19 /**< A dynamic array is too big */
+#define SP_ERROR_TRACKER_BOUNDS 20 /**< Tracker stack is out of bounds */
+#define SP_ERROR_INVALID_NATIVE 21 /**< Native was pending or invalid */
+#define SP_ERROR_PARAMS_MAX 22 /**< Maximum number of parameters reached */
+#define SP_ERROR_NATIVE 23 /**< Error originates from a native */
+#define SP_ERROR_NOT_RUNNABLE 24 /**< Function or plugin is not runnable */
+#define SP_ERROR_ABORTED 25 /**< Function call was aborted */
+
+/**
+ * @endsection
+ */
+
+/**
+ * Gets a function id from a function name.
+ *
+ * @param plugin Handle of the plugin that contains the function.
+ Pass INVALID_HANDLE to search in the calling plugin.
+ * @param name Name of the function.
+ * @return Function id or INVALID_FUNCTION if not found.
+ * @error Invalid or corrupt plugin handle.
+ */
+native Function:GetFunctionByName(Handle:plugin, const String:name[]);
+
+/**
+ * Creates a global forward.
+ *
+ * @note The name used to create the forward is used as its public function in all target plugins.
+ * @note This is ideal for global, static forwards that are never changed.
+ * @note Global forwards cannot be cloned.
+ * @note Use CloseHandle() to destroy these.
+ *
+ * @param name Name of public function to use in forward.
+ * @param type Execution type to be used.
+ * @param ... Variable number of parameter types (up to 32).
+ * @return Handle to new global forward.
+ * @error More than 32 paramater types passed.
+ */
+native Handle:CreateGlobalForward(const String:name[], ExecType:type, ParamType:...);
+
+/**
+ * Creates a private forward.
+ *
+ * @note No functions are automatically added. Use AddToForward() to do this.
+ * @note Private forwards can be cloned.
+ * @note Use CloseHandle() to destroy these.
+ *
+ * @param type Execution type to be used.
+ * @param ... Variable number of parameter types (up to 32).
+ * @return Handle to new private forward.
+ * @error More than 32 paramater types passed.
+ */
+native Handle:CreateForward(ExecType:type, ParamType:...);
+
+/**
+ * Returns the number of functions in a global or private forward's call list.
+ *
+ * @param fwd Handle to global or private forward.
+ * @return Number of functions in forward.
+ * @error Invalid or corrupt forward handle.
+ */
+native GetForwardFunctionCount(Handle:fwd);
+
+/**
+ * Adds a function to a private forward's call list.
+ *
+ * @note Cannot be used during an incompleted call.
+ *
+ * @param fwd Handle to private forward.
+ * @param plugin Handle of the plugin that contains the function.
+ * Pass INVALID_HANDLE to specify the calling plugin.
+ * @param func Function to add to forward.
+ * @return True on success, false otherwise.
+ * @error Invalid or corrupt private forward handle, invalid or corrupt plugin handle, or invalid function.
+ */
+native bool:AddToForward(Handle:fwd, Handle:plugin, Function:func);
+
+/**
+ * Removes a function from a private forward's call list.
+ *
+ * @note Only removes one instance.
+ * @note Functions will be removed automatically if their parent plugin is unloaded.
+ *
+ * @param fwd Handle to private forward.
+ * @param plugin Handle of the plugin that contains the function.
+ * Pass INVALID_HANDLE to specify the calling plugin.
+ * @param func Function to remove from forward.
+ * @return True on success, false otherwise.
+ * @error Invalid or corrupt private forward handle, invalid or corrupt plugin handle, or invalid function.
+ */
+native bool:RemoveFromForward(Handle:fwd, Handle:plugin, Function:func);
+
+/**
+ * Removes all instances of a plugin from a private forward's call list.
+ *
+ * @note Functions will be removed automatically if their parent plugin is unloaded.
+ *
+ * @param fwd Handle to private forward.
+ * @param plugin Handle of the plugin to remove instances of.
+ * Pass INVALID_HANDLE to specify the calling plugin.
+ * @return Number of functions removed from forward.
+ * @error Invalid or corrupt private forward handle or invalid or corrupt plugin handle.
+ */
+native RemoveAllFromForward(Handle:fwd, Handle:plugin);
+
+/**
+ * Starts a call to functions in a forward's call list.
+ *
+ * @note Cannot be used during an incompleted call.
+ *
+ * @param fwd Handle to global or private forward.
+ * @noreturn
+ * @error Invalid or corrupt forward handle or called before another call has completed.
+ */
+native Call_StartForward(Handle:fwd);
+
+/**
+ * Starts a call to a function.
+ *
+ * @note Cannot be used during an incompleted call.
+ *
+ * @param plugin Handle of the plugin that contains the function.
+ * Pass INVALID_HANDLE to specify the calling plugin.
+ * @param func Function to call.
+ * @noreturn
+ * @error Invalid or corrupt plugin handle, invalid function, or called before another call has completed.
+ */
+native Call_StartFunction(Handle:plugin, Function:func);
+
+/**
+ * Pushes a cell onto the current call.
+ *
+ * @note Cannot be used before a call has been started.
+ *
+ * @param value Cell value to push.
+ * @noreturn
+ * @error Called before a call has been started.
+ */
+native Call_PushCell(any:value);
+
+/**
+ * Pushes a cell by reference onto the current call.
+ *
+ * @note Cannot be used before a call has been started.
+ *
+ * @param value Cell reference to push.
+ * @noreturn
+ * @error Called before a call has been started.
+ */
+native Call_PushCellRef(&any:value);
+
+/**
+ * Pushes a float onto the current call.
+ *
+ * @note Cannot be used before a call has been started.
+ *
+ * @param value Floating point value to push.
+ * @noreturn
+ * @error Called before a call has been started.
+ */
+native Call_PushFloat(Float:value);
+
+/**
+ * Pushes a float by reference onto the current call.
+ *
+ * @note Cannot be used before a call has been started.
+ *
+ * @param value Floating point reference to push.
+ * @noreturn
+ * @error Called before a call has been started.
+ */
+native Call_PushFloatRef(&Float:value);
+
+/**
+ * Pushes an array onto the current call.
+ *
+ * @note Changes to array are not copied back to caller. Use PushArrayEx() to do this.
+ * @note Cannot be used before a call has been started.
+ *
+ * @param value Array to push.
+ * @param size Size of array.
+ * @noreturn
+ * @error Called before a call has been started.
+ */
+native Call_PushArray(const any:value[], size);
+
+/**
+ * Pushes an array onto the current call.
+ *
+ * @note Cannot be used before a call has been started.
+ *
+ * @param value Array to push.
+ * @param size Size of array.
+ * @param cpflags Whether or not changes should be copied back to the input array.
+ * See SP_PARAM_* constants for details.
+ * @noreturn
+ * @error Called before a call has been started.
+ */
+native Call_PushArrayEx(any:value[], size, cpflags);
+
+/**
+ * Pushes a string onto the current call.
+ *
+ * @note Changes to string are not copied back to caller. Use PushStringEx() to do this.
+ * @note Cannot be used before a call has been started.
+ *
+ * @param value String to push.
+ * @noreturn
+ * @error Called before a call has been started.
+ */
+native Call_PushString(const String:value[]);
+
+/**
+ * Pushes a string onto the current call.
+ *
+ * @note Cannot be used before a call has been started.
+ *
+ * @param value String to push.
+ * @param length Length of string buffer.
+ * @param szflags Flags determining how string should be handled.
+ * See SP_PARAM_STRING_* constants for details.
+ * The default (0) is to push ASCII.
+ * @param cpflags Whether or not changes should be copied back to the input array.
+ * See SP_PARAM_* constants for details.
+ * @noreturn
+ * @error Called before a call has been started.
+ */
+native Call_PushStringEx(String:value[], length, szflags, cpflags);
+
+/**
+ * Completes a call to a function or forward's call list.
+ *
+ * @note Cannot be used before a call has been started.
+ *
+ * @param result Return value of function or forward's call list.
+ * @return SP_ERROR_NONE on success, any other integer on failure.
+ * @error Called before a call has been started.
+ */
+native Call_Finish(&any:result=0);
+
+/**
+ * Cancels a call to a function or forward's call list.
+ *
+ * @note Cannot be used before a call has been started.
+ *
+ * @noreturn
+ * @error Called before a call has been started.
+ */
+native Call_Cancel();
+
+/**
+ * Defines a native function.
+ *
+ * It is not necessary to validate the parameter count
+ *
+ * @param plugin Handle of the calling plugin.
+ * @param numParams Number of parameters passed to the native.
+ * @return Value for the native call to return.
+ */
+functag public NativeCall(Handle:plugin, numParams);
+
+/**
+ * Creates a dynamic native. This should only be called in AskPluginLoad(), or
+ * else you risk not having your native shared with other plugins.
+ *
+ * @param name Name of the dynamic native; must be unique amongst
+ * all other registered dynamic natives.
+ * @param func Function to use as the dynamic native.
+ * @noreturn
+ */
+native CreateNative(const String:name[], NativeCall:func);
+
+/**
+ * Throws an error in the calling plugin of a native, instead of your own plugin.
+ *
+ * @param error Error code to use.
+ * @param fmt Error message format.
+ * @param ... Format arguments.
+ */
+native ThrowNativeError(error, const String:fmt[], any:...);
+
+/**
+ * Retrieves the string length from a native parameter string. This is useful
+ * fetching the entire string using dynamic arrays.
+ * @note If this function succeeds, Get/SetNativeString will also succeed.
+ *
+ * @param param Parameter number, starting from 1.
+ * @param length Stores the length of the string.
+ * @return SP_ERROR_NONE on success, any other integer on failure.
+ * @error Invalid parameter number or calling from a non-native function.
+ */
+native GetNativeStringLength(param, &length);
+
+/**
+ * Retrieves a string from a native parameter.
+ * @note Output conditions are undefined on failure.
+ *
+ * @param param Parameter number, starting from 1.
+ * @param buffer Buffer to store the string in.
+ * @param maxlength Maximum length of the buffer.
+ * @param bytes Optionally store the number of bytes written.
+ * @return SP_ERROR_NONE on success, any other integer on failure.
+ * @error Invalid parameter number or calling from a non-native function.
+ */
+native GetNativeString(param, String:buffer[], maxlength, &bytes=0);
+
+/**
+ * Sets a string in a native parameter.
+ * @note Output conditions are undefined on failure.
+ *
+ * @param param Parameter number, starting from 1.
+ * @param source Source string to use.
+ * @param maxlength Maximum number of bytes to write.
+ * @param utf8 If false, string will not be written
+ * with UTF8 safety.
+ * @param bytes Optionally store the number of bytes written.
+ * @return SP_ERROR_NONE on success, any other integer on failure.
+ * @error Invalid parameter number or calling from a non-native function.
+ */
+native SetNativeString(param, const String:source[], maxlength, bool:utf8=true, &bytes=0);
+
+/**
+ * Gets a cell from a native parameter.
+ *
+ * @param param Parameter number, starting from 1.
+ * @return Cell value at the parameter number.
+ * @error Invalid parameter number or calling from a non-native function.
+ */
+native any:GetNativeCell(param);
+
+/**
+ * Gets a cell from a native parameter, by reference.
+ *
+ * @param param Parameter number, starting from 1.
+ * @return Cell value at the parameter number.
+ * @error Invalid parameter number or calling from a non-native function.
+ */
+native any:GetNativeCellRef(param);
+
+/**
+ * Sets a cell from a native parameter, by reference.
+ *
+ * @param param Parameter number, starting from 1.
+ * @param value Cell value at the parameter number to set by reference.
+ * @noreturn
+ * @error Invalid parameter number or calling from a non-native function.
+ */
+native SetNativeCellRef(param, any:value);
+
+/**
+ * Gets an array from a native parameter (always by reference).
+ *
+ * @param param Parameter number, starting from 1.
+ * @param local Local array to copy into.
+ * @param size Maximum size of local array.
+ * @return SP_ERROR_NONE on success, anything else on failure.
+ * @error Invalid parameter number or calling from a non-native function.
+ */
+native GetNativeArray(param, any:local[], size);
+
+/**
+ * Copies a local array into a native parameter array (always by reference).
+ *
+ * @param param Parameter number, starting from 1.
+ * @param local Local array to copy from.
+ * @param size Size of the local array to copy.
+ * @return SP_ERROR_NONE on success, anything else on failure.
+ * @error Invalid parameter number or calling from a non-native function.
+ */
+native SetNativeArray(param, const any:local[], size);
+
+/**
+ * Formats a string using parameters from a native.
+ *
+ * @note All parameter indexes start at 1.
+ * @note If the input and output buffers overlap, the contents
+ * of the output buffer at the end is undefined.
+ *
+ * @param out_param Output parameter number to write to. If 0, out_string is used.
+ * @param fmt_param Format parameter number. If 0, fmt_string is used.
+ * @param vararg_param First variable parameter number.
+ * @param out_len Output string buffer maximum length (always required).
+ * @param written Optionally stores the number of bytes written.
+ * @param out_string Output string buffer to use if out_param is not used.
+ * @param fmt_string Format string to use if fmt_param is not used.
+ * @return SP_ERROR_NONE on success, anything else on failure.
+ */
+native FormatNativeString(out_param,
+ fmt_param,
+ vararg_param,
+ out_len,
+ &written=0,
+ String:out_string[]="",
+ const String:fmt_string[]="");
+
+/**
+ * Defines a RequestFrame Callback.
+ *
+ * @param data Data passed to the RequestFrame native.
+ * @noreturn
+ */
+functag public RequestFrameCallback(any:data);
+
+/**
+ * Creates a single use Next Frame hook.
+ *
+ * @param Function Function to call on the next frame.
+ * @param data Value to be passed on the invocation of the Function.
+ * @noreturn
+ */
+native RequestFrame(RequestFrameCallback:Function, any:data=0);
diff --git a/sourcemod-1.5-dev/scripting/include/geoip.inc b/sourcemod-1.5-dev/scripting/include/geoip.inc
new file mode 100644
index 0000000..3df697e
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/geoip.inc
@@ -0,0 +1,102 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _geoip_included
+ #endinput
+#endif
+#define _geoip_included
+
+#include <core>
+
+/**
+ * @section IP addresses can contain ports, the ports will be stripped out.
+ */
+
+/**
+ * Gets the two character country code from an IP address. (US, CA, etc)
+ *
+ * @param ip Ip to determine the country code.
+ * @param ccode Destination string buffer to store the code.
+ * @return True on success, false if no country found.
+ */
+native bool:GeoipCode2(const String:ip[], String:ccode[3]);
+
+/**
+ * Gets the three character country code from an IP address. (USA, CAN, etc)
+ *
+ * @param ip Ip to determine the country code.
+ * @param ccode Destination string buffer to store the code.
+ * @return True on success, false if no country found.
+ */
+native bool:GeoipCode3(const String:ip[], String:ccode[4]);
+
+/**
+ * Gets the full country name. (max length of output string is 45)
+ *
+ * @param ip Ip to determine the country code.
+ * @param name Destination string buffer to store the country name.
+ * @param maxlength Maximum length of output string buffer.
+ * @return True on success, false if no country found.
+ */
+native bool:GeoipCountry(const String:ip[], String:name[], maxlength);
+
+/**
+ * @endsection
+ */
+
+/**
+ * Do not edit below this line!
+ */
+public Extension:__ext_geoip =
+{
+ name = "GeoIP",
+ file = "geoip.ext",
+#if defined AUTOLOAD_EXTENSIONS
+ autoload = 1,
+#else
+ autoload = 0,
+#endif
+#if defined REQUIRE_EXTENSIONS
+ required = 1,
+#else
+ required = 0,
+#endif
+};
+
+#if !defined REQUIRE_EXTENSIONS
+public __ext_geoip_SetNTVOptional()
+{
+ MarkNativeAsOptional("GeoipCode2");
+ MarkNativeAsOptional("GeoipCode3");
+ MarkNativeAsOptional("GeoipCountry");
+}
+#endif
diff --git a/sourcemod-1.5-dev/scripting/include/halflife.inc b/sourcemod-1.5-dev/scripting/include/halflife.inc
new file mode 100644
index 0000000..c734e90
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/halflife.inc
@@ -0,0 +1,625 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _halflife_included
+ #endinput
+#endif
+#define _halflife_included
+
+#define SOURCE_SDK_UNKNOWN 0 /**< Could not determine the engine version */
+#define SOURCE_SDK_ORIGINAL 10 /**< Original Source engine (still used by "The Ship") */
+#define SOURCE_SDK_DARKMESSIAH 15 /**< Modified version of original engine used by Dark Messiah (no SDK) */
+#define SOURCE_SDK_EPISODE1 20 /**< SDK+Engine released after Episode 1 */
+#define SOURCE_SDK_EPISODE2 30 /**< SDK+Engine released after Episode 2/Orange Box */
+#define SOURCE_SDK_BLOODYGOODTIME 32 /**< Modified version of ep2 engine used by Bloody Good Time (no SDK) */
+#define SOURCE_SDK_EYE 33 /**< Modified version of ep2 engine used by E.Y.E Divine Cybermancy (no SDK) */
+#define SOURCE_SDK_CSS 34 /**< Sometime-older version of Source 2009 SDK+Engine, used for Counter-Strike: Source */
+#define SOURCE_SDK_EPISODE2VALVE 35 /**< SDK+Engine released after Episode 2/Orange Box, "Source 2009" or "Source MP" */
+#define SOURCE_SDK_LEFT4DEAD 40 /**< Engine released after Left 4 Dead (no SDK yet) */
+#define SOURCE_SDK_LEFT4DEAD2 50 /**< Engine released after Left 4 Dead 2 (no SDK yet) */
+#define SOURCE_SDK_ALIENSWARM 60 /**< SDK+Engine released after Alien Swarm */
+#define SOURCE_SDK_CSGO 80 /**< Engine released after CS:GO (no SDK yet) */
+#define SOURCE_SDK_DOTA 90 /**< Engine released after Dota 2 (no SDK) */
+
+#define MOTDPANEL_TYPE_TEXT 0 /**< Treat msg as plain text */
+#define MOTDPANEL_TYPE_INDEX 1 /**< Msg is auto determined by the engine */
+#define MOTDPANEL_TYPE_URL 2 /**< Treat msg as an URL link */
+#define MOTDPANEL_TYPE_FILE 3 /**< Treat msg as a filename to be openned */
+
+enum DialogType
+{
+ DialogType_Msg = 0, /**< just an on screen message */
+ DialogType_Menu, /**< an options menu */
+ DialogType_Text, /**< a richtext dialog */
+ DialogType_Entry, /**< an entry box */
+ DialogType_AskConnect /**< ask the client to connect to a specified IP */
+};
+
+enum EngineVersion
+{
+ Engine_Unknown, /**< Could not determine the engine version */
+ Engine_Original, /**< Original Source Engine (used by The Ship) */
+ Engine_SourceSDK2006, /**< Episode 1 Source Engine (second major SDK) */
+ Engine_SourceSDK2007, /**< Orange Box Source Engine (third major SDK) */
+ Engine_Left4Dead, /**< Left 4 Dead */
+ Engine_DarkMessiah, /**< Dark Messiah Multiplayer (based on original engine) */
+ Engine_Left4Dead2 = 7, /**< Left 4 Dead 2 */
+ Engine_AlienSwarm, /**< Alien Swarm (and Alien Swarm SDK) */
+ Engine_BloodyGoodTime, /**< Bloody Good Time */
+ Engine_EYE, /**< E.Y.E Divine Cybermancy */
+ Engine_Portal2, /**< Portal 2 */
+ Engine_CSGO, /**< Counter-Strike: Global Offensive */
+ Engine_CSS, /**< Counter-Strike: Source */
+ Engine_DOTA, /**< Dota 2 */
+ Engine_HL2DM, /**< Half-Life 2 Deathmatch */
+ Engine_DODS, /**< Day of Defeat: Source */
+ Engine_TF2, /**< Team Fortress 2 */
+ Engine_NuclearDawn, /**< Nuclear Dawn */
+ Engine_SDK2013, /**< Source SDK 2013 */
+ Engine_Blade, /**< Blade Symphony */
+ Engine_Insurgency, /**< Insurgency (2013 Retail version)*/
+ Engine_Contagion, /**< Contagion */
+};
+
+#define INVALID_ENT_REFERENCE 0xFFFFFFFF
+
+/**
+ * Logs a generic message to the HL2 logs.
+ *
+ * @param format String format.
+ * @param ... Format arguments.
+ * @noreturn
+ */
+native LogToGame(const String:format[], any:...);
+
+/**
+ * Sets the seed value for the global Half-Life 2 Random Stream.
+ *
+ * @param seed Seed value.
+ * @noreturn
+ */
+native SetRandomSeed(seed);
+
+/**
+ * Returns a random floating point number from the Half-Life 2 Random Stream.
+ *
+ * @param fMin Minimum random bound.
+ * @param fMax Maximum random bound.
+ * @return A random number between (inclusive) fMin and fMax.
+ */
+native Float:GetRandomFloat(Float:fMin=0.0, Float:fMax=1.0);
+
+/**
+ * Returns a random number from the Half-Life 2 Random Stream.
+ *
+ * @param nmin Minimum random bound.
+ * @param nmax Maximum random bound.
+ * @return A random number between (inclusive) nmin and nmax.
+ */
+native GetRandomInt(nmin, nmax);
+
+/**
+ * Returns whether a map is valid or not.
+ *
+ * @param map Map name, excluding .bsp extension.
+ * @return True if valid, false otherwise.
+ */
+native bool:IsMapValid(const String:map[]);
+
+/**
+ * Returns whether the server is dedicated.
+ *
+ * @return True if dedicated, false otherwise.
+ */
+native bool:IsDedicatedServer();
+
+/**
+ * Returns a high-precision time value for profiling the engine.
+ *
+ * @return A floating point time value.
+ */
+native Float:GetEngineTime();
+
+/**
+ * Returns the game time based on the game tick.
+ *
+ * @return Game tick time.
+ */
+native Float:GetGameTime();
+
+/**
+ * Returns the game's internal tick count.
+ *
+ * @return Game tick count.
+ */
+native GetGameTickCount();
+
+/**
+ * Returns the game description from the mod.
+ *
+ * @param buffer Buffer to store the description.
+ * @param maxlength Maximum size of the buffer.
+ * @param original If true, retrieves the original game description,
+ * ignoring any potential hooks from plugins.
+ * @return Number of bytes written to the buffer (UTF-8 safe).
+ */
+native GetGameDescription(String:buffer[], maxlength, bool:original=false);
+
+/**
+ * Returns the name of the game's directory.
+ *
+ * @param buffer Buffer to store the directory name.
+ * @param maxlength Maximum size of the buffer.
+ *
+ * return Number of bytes written to the buffer (UTF-8 safe).
+ */
+native GetGameFolderName(String:buffer[], maxlength);
+
+/**
+ * Returns the current map name.
+ *
+ * @param buffer Buffer to store map name.
+ * @param maxlength Maximum length of buffer.
+ * @return Number of bytes written (UTF-8 safe).
+ */
+native GetCurrentMap(String:buffer[], maxlength);
+
+/**
+ * Precaches a given model.
+ *
+ * @param model Name of the model to precache.
+ * @param preload If preload is true the file will be precached before level startup.
+ * @return Returns the model index, 0 for error.
+ */
+native PrecacheModel(const String:model[], bool:preload=false);
+
+/**
+ * Precaches a given sentence file.
+ *
+ * @param file Name of the sentence file to precache.
+ * @param preload If preload is true the file will be precached before level startup.
+ * @return Returns a sentence file index.
+ */
+native PrecacheSentenceFile(const String:file[], bool:preload=false);
+
+/**
+ * Precaches a given decal.
+ *
+ * @param decal Name of the decal to precache.
+ * @param preload If preload is true the file will be precached before level startup.
+ * @return Returns a decal index.
+ */
+native PrecacheDecal(const String:decal[], bool:preload=false);
+
+/**
+ * Precaches a given generic file.
+ *
+ * @param generic Name of the generic file to precache.
+ * @param preload If preload is true the file will be precached before level startup.
+ * @return Returns a generic file index.
+ */
+native PrecacheGeneric(const String:generic[], bool:preload=false);
+
+/**
+ * Returns if a given model is precached.
+ *
+ * @param model Name of the model to check.
+ * @return True if precached, false otherwise.
+ */
+native bool:IsModelPrecached(const String:model[]);
+
+/**
+ * Returns if a given decal is precached.
+ *
+ * @param decal Name of the decal to check.
+ * @return True if precached, false otherwise.
+ */
+native bool:IsDecalPrecached(const String:decal[]);
+
+/**
+ * Returns if a given generic file is precached.
+ *
+ * @param generic Name of the generic file to check.
+ * @return True if precached, false otherwise.
+ */
+native bool:IsGenericPrecached(const String:generic[]);
+
+/**
+ * Precaches a given sound.
+ *
+ * @param sound Name of the sound to precache.
+ * @param preload If preload is true the file will be precached before level startup.
+ * @return True if successfully precached, false otherwise.
+ */
+native bool:PrecacheSound(const String:sound[], bool:preload=false);
+
+/**
+ * Returns if a given sound is precached.
+ *
+ * @param sound Name of the sound to check.
+ * @return True if precached, false otherwise.
+ */
+native bool:IsSoundPrecached(const String:sound[]);
+
+/**
+ * Creates different types of ingame messages.
+ *
+ * @param client Index of the client.
+ * @param kv KeyValues handle to set the menu keys and options. (Check iserverplugin.h for more information).
+ * @param type Message type to display ingame.
+ * @noreturn
+ * @error Invalid client index, or client not connected.
+ */
+native CreateDialog(client, Handle:kv, DialogType:type);
+
+/**
+ * Guesses the SDK version a mod was compiled against. If nothing
+ * specific is known about the game, the engine version is used instead.
+ *
+ * The return values are guaranteed to increase chronologically (that is,
+ * a later release will have a higher value).
+ *
+ * @return SOURCE_SDK version code.
+ */
+#pragma deprecated See GetEngineVersion()
+native GuessSDKVersion();
+
+/**
+ * Gets the engine version that the currently-loaded SM core was compiled against.
+ *
+ * The engine version values are not guaranteed to be in any particular order,
+ * and should only be compared by (in)equality.
+ *
+ * @return An EngineVersion value.
+ */
+native EngineVersion:GetEngineVersion();
+
+/**
+ * Prints a message to a specific client in the chat area.
+ *
+ * @param client Client index.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ * @error If the client is not connected an error will be thrown.
+ */
+native PrintToChat(client, const String:format[], any:...);
+
+/**
+ * Prints a message to all clients in the chat area.
+ *
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock PrintToChatAll(const String:format[], any:...)
+{
+ decl String:buffer[192];
+
+ for (new i = 1; i <= MaxClients; i++)
+ {
+ if (IsClientInGame(i))
+ {
+ SetGlobalTransTarget(i);
+ VFormat(buffer, sizeof(buffer), format, 2);
+ PrintToChat(i, "%s", buffer);
+ }
+ }
+}
+
+/**
+ * Prints a message to a specific client in the center of the screen.
+ *
+ * @param client Client index.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ * @error If the client is not connected an error will be thrown.
+ */
+native PrintCenterText(client, const String:format[], any:...);
+
+/**
+ * Prints a message to all clients in the center of the screen.
+ *
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock PrintCenterTextAll(const String:format[], any:...)
+{
+ decl String:buffer[192];
+
+ for (new i = 1; i <= MaxClients; i++)
+ {
+ if (IsClientInGame(i))
+ {
+ SetGlobalTransTarget(i);
+ VFormat(buffer, sizeof(buffer), format, 2);
+ PrintCenterText(i, "%s", buffer);
+ }
+ }
+}
+
+/**
+ * Prints a message to a specific client with a hint box.
+ *
+ * @param client Client index.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ * @error If the client is not connected an error will be thrown.
+ */
+native PrintHintText(client, const String:format[], any:...);
+
+/**
+ * Prints a message to all clients with a hint box.
+ *
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock PrintHintTextToAll(const String:format[], any:...)
+{
+ decl String:buffer[192];
+
+ for (new i = 1; i <= MaxClients; i++)
+ {
+ if (IsClientInGame(i))
+ {
+ SetGlobalTransTarget(i);
+ VFormat(buffer, sizeof(buffer), format, 2);
+ PrintHintText(i, "%s", buffer);
+ }
+ }
+}
+
+/**
+ * Shows a VGUI panel to a specific client.
+ *
+ * @param client Client index.
+ * @param name Panel type name (Check viewport_panel_names.h to see a list of
+ * some panel names).
+ * @param Kv KeyValues handle with all the data for the panel setup (Depends
+ * on the panel type and may be unused).
+ * @param show True to show the panel, or false to remove it from the client screen.
+ * @noreturn
+ * @error If the client is not connected an error will be thrown.
+ */
+native ShowVGUIPanel(client, const String:name[], Handle:Kv=INVALID_HANDLE, bool:show=true);
+
+/**
+ * Creates a HUD synchronization object. This object is used to automatically assign and
+ * re-use channels for a set of messages.
+ *
+ * The HUD has a hardcoded number of channels (usually 6) for displaying
+ * text. You can use any channel for any area of the screen. Text on
+ * different channels can overlap, but text on the same channel will
+ * erase the old text first. This overlapping and overwriting gets problematic.
+ *
+ * A HUD synchronization object automatically selects channels for you based on
+ * the following heuristics:
+ * - If channel X was last used by the object, and hasn't been modified again,
+ * channel X gets re-used.
+ * - Otherwise, a new channel is chosen based on the least-recently-used channel.
+ *
+ * This ensures that if you display text on a sync object, that the previous text
+ * displayed on it will always be cleared first. This is because your new text
+ * will either overwrite the old text on the same channel, or because another
+ * channel has already erased your text.
+ *
+ * Note that messages can still overlap if they are on different synchronization
+ * objects, or they are displayed to manual channels.
+ *
+ * These are particularly useful for displaying repeating or refreshing HUD text, in
+ * addition to displaying multiple message sets in one area of the screen (for example,
+ * center-say messages that may pop up randomly that you don't want to overlap each
+ * other).
+ *
+ * @return New HUD synchronization object.
+ * The Handle can be closed with CloseHandle().
+ * If HUD text is not supported on this mod, then
+ * INVALID_HANDLE is returned.
+ */
+native Handle:CreateHudSynchronizer();
+
+/**
+ * Sets the HUD parameters for drawing text. These parameters are stored
+ * globally, although nothing other than this function and SetHudTextParamsEx
+ * modify them.
+ *
+ * You must call this function before drawing text. If you are drawing
+ * text to multiple clients, you can set the parameters once, since
+ * they won't be modified. However, as soon as you pass control back
+ * to other plugins, you must reset the parameters next time you draw.
+ *
+ * @param x x coordinate, from 0 to 1. -1.0 is the center.
+ * @param y y coordinate, from 0 to 1. -1.0 is the center.
+ * @param holdTime Number of seconds to hold the text.
+ * @param r Red color value.
+ * @param g Green color value.
+ * @param b Blue color value.
+ * @param a Alpha transparency value.
+ * @param effect 0/1 causes the text to fade in and fade out.
+ * 2 causes the text to flash[?].
+ * @param fxTime Duration of chosen effect (may not apply to all effects).
+ * @param fadeIn Number of seconds to spend fading in.
+ * @param fadeOut Number of seconds to spend fading out.
+ * @noreturn
+ */
+native SetHudTextParams(Float:x, Float:y, Float:holdTime, r, g, b, a, effect = 0,
+ Float:fxTime=6.0, Float:fadeIn=0.1, Float:fadeOut=0.2);
+
+/**
+ * Sets the HUD parameters for drawing text. These parameters are stored
+ * globally, although nothing other than this function and SetHudTextParams
+ * modify them.
+ *
+ * This is the same as SetHudTextParams(), except it lets you set the alternate
+ * color for when effects require it.
+ *
+ * @param x x coordinate, from 0 to 1. -1.0 is the center.
+ * @param y y coordinate, from 0 to 1. -1.0 is the center.
+ * @param holdTime Number of seconds to hold the text.
+ * @param color1 First color set, array values being [red, green, blue, alpha]
+ * @param color2 Second color set, array values being [red, green, blue, alpha]
+ * @param effect 0/1 causes the text to fade in and fade out.
+ * 2 causes the text to flash[?].
+ * @param fxTime Duration of chosen effect (may not apply to all effects).
+ * @param fadeIn Number of seconds to spend fading in.
+ * @param fadeOut Number of seconds to spend fading out.
+ * @noreturn
+ */
+native SetHudTextParamsEx(Float:x, Float:y, Float:holdTime, color1[4],
+ color2[4]={255,255,255,0}, effect = 0, Float:fxTime=6.0,
+ Float:fadeIn=0.1, Float:fadeOut=0.2);
+
+/**
+ * Shows a synchronized HUD message to a client.
+ *
+ * As of this writing, only TF, HL2MP, and SourceForts support HUD Text.
+ *
+ * @param client Client index to send the message to.
+ * @param sync Synchronization object.
+ * @param message Message text or formatting rules.
+ * @param ... Message formatting parameters.
+ * @return -1 on failure, anything else on success.
+ * This function fails if the mod does not support it.
+ * @error Client not in-game, or sync object not valid.
+ */
+native ShowSyncHudText(client, Handle:sync, const String:message[], any:...);
+
+/**
+ * Clears the text on a synchronized HUD channel.
+ *
+ * This is not the same as sending "" because it guarantees that it won't
+ * overwrite text on another channel. For example, consider the scenario:
+ *
+ * 1. Your synchronized message goes to channel 3.
+ * 2. Someone else's non-synchronized message goes to channel 3.
+ *
+ * If you were to simply send "" on your synchronized message,
+ * then someone else's text could be overwritten.
+ *
+ * @param client Client index to send the message to.
+ * @param sync Synchronization object.
+ * @noreturn
+ * @error Client not in-game, or sync object not valid.
+ */
+native ClearSyncHud(client, Handle:sync);
+
+/**
+ * Shows a HUD message to a client on the given channel.
+ *
+ * As of this writing, only TF, HL2MP, and SourceForts support HUD Text.
+ *
+ * @param client Client index to send the message to.
+ * @param channel A channel number.
+ * If -1, then a channel will automatically be selected
+ * based on the least-recently-used channel. If the
+ * channel is any other number, it will be modulo'd with
+ * the channel count to get a final channel number.
+ * @param message Message text or formatting rules.
+ * @param ... Message formatting parameters.
+ * @return -1 on failure (lack of mod support).
+ * Any other return value is the channel number that was
+ * used to render the text.
+ */
+native ShowHudText(client, channel, const String:message[], any:...);
+
+/**
+ * Shows a MOTD panel to a specific client.
+ *
+ * @param client Client index.
+ * @param title Title of the panel (printed on the top border of the window).
+ * @param msg Contents of the panel, it can be treated as an url, filename or plain text
+ * depending on the type parameter (WARNING: msg has to be 192 bytes maximum!)
+ * @param type Determines the way to treat the message body of the panel.
+ * @noreturn
+ * @error If the client is not connected an error will be thrown.
+ */
+stock ShowMOTDPanel(client, const String:title[], const String:msg[], type=MOTDPANEL_TYPE_INDEX)
+{
+ decl String:num[3];
+ new Handle:Kv = CreateKeyValues("data");
+ IntToString(type, num, sizeof(num));
+
+ KvSetString(Kv, "title", title);
+ KvSetString(Kv, "type", num);
+ KvSetString(Kv, "msg", msg);
+ ShowVGUIPanel(client, "info", Kv);
+ CloseHandle(Kv);
+}
+
+/**
+ * Displays a panel asking the client to connect to a specified IP.
+ *
+ * @param client Client index.
+ * @param time Duration to hold the panel on the client's screen.
+ * @param ip Destination IP.
+ * @param password Password to connect to the destination IP. The client will be able to see this.
+ * @noreturn
+ */
+stock DisplayAskConnectBox(client, Float:time, const String:ip[], const String:password[] = "")
+{
+ decl String:destination[288];
+ FormatEx(destination, sizeof(destination), "%s/%s", ip, password);
+ new Handle:Kv = CreateKeyValues("data");
+ KvSetFloat(Kv, "time", time);
+ KvSetString(Kv, "title", destination);
+ CreateDialog(client, Kv, DialogType_AskConnect);
+ CloseHandle(Kv);
+}
+
+/**
+ * Converts an entity index into a serial encoded entity reference.
+ *
+ * @param entity Entity index.
+ * @return Entity reference.
+ */
+native EntIndexToEntRef(entity);
+
+/**
+ * Retrieves the entity index from a reference.
+ *
+ * @param ref Entity reference.
+ * @return Entity index.
+ */
+native EntRefToEntIndex(ref);
+
+/**
+ * Converts a reference into a backwards compatible version.
+ *
+ * @param ref Entity reference.
+ * @return Bcompat reference.
+ */
+native MakeCompatEntRef(ref);
+
diff --git a/sourcemod-1.5-dev/scripting/include/handles.inc b/sourcemod-1.5-dev/scripting/include/handles.inc
new file mode 100644
index 0000000..053ad6f
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/handles.inc
@@ -0,0 +1,96 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _handles_included
+ #endinput
+#endif
+#define _handles_included
+
+/**
+ * Handle helper macros.
+ */
+enum Handle
+{
+ INVALID_HANDLE = 0,
+};
+
+
+/**
+ * Closes a Handle. If the handle has multiple copies open,
+ * it is not destroyed unless all copies are closed.
+ *
+ * @note Closing a Handle has a different meaning for each Handle type. Make
+ * sure you read the documentation on whatever provided the Handle.
+ *
+ * @param hndl Handle to close.
+ * @return True if successful, false if not closeable.
+ * @error Invalid handles will cause a run time error.
+ */
+native bool:CloseHandle(Handle:hndl);
+
+/**
+ * Clones a Handle. When passing handles in between plugins, caching handles
+ * can result in accidental invalidation when one plugin releases the Handle, or is its owner
+ * is unloaded from memory. To prevent this, the Handle may be "cloned" with a new owner.
+ *
+ * @note Usually, you will be cloning Handles for other plugins. This means that if you clone
+ * the Handle without specifying the new owner, it will assume the identity of your original calling
+ * plugin, which is not very useful. You should either specify that the receiving plugin should
+ * clone the handle on its own, or you should explicitly clone the Handle using the receiving plugin's
+ * identity Handle.
+ *
+ * @param hndl Handle to clone/duplicate.
+ * @param plugin Optional Handle to another plugin to mark as the new owner.
+ * If no owner is passed, the owner becomes the calling plugin.
+ * @return Handle on success, INVALID_HANDLE if not cloneable.
+ * @error Invalid handles will cause a run time error.
+ */
+native Handle:CloneHandle(Handle:hndl, Handle:plugin=INVALID_HANDLE);
+
+/**
+ * Do not use this function. Returns if a Handle and its contents
+ * are readable, whereas INVALID_HANDLE only checks for the absence
+ * of a Handle.
+ *
+ * This function is intended only for tests where the validity of a
+ * Handle can absolutely not be known.
+ *
+ * Do not use this to check the return values of functions, or to
+ * check if timers should be closed (except in very rare cases).
+ * This function is for very specific usage and using it for general
+ * purpose routines can and will hide very subtle bugs.
+ *
+ * @param hndl Handle to test for validity.
+ * @return True if handle is valid, false otherwise.
+ */
+#pragma deprecated Do not use this function.
+native bool:IsValidHandle(Handle:hndl);
diff --git a/sourcemod-1.5-dev/scripting/include/helpers.inc b/sourcemod-1.5-dev/scripting/include/helpers.inc
new file mode 100644
index 0000000..3b70165
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/helpers.inc
@@ -0,0 +1,293 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _helpers_included
+ #endinput
+#endif
+#define _helpers_included
+
+/**
+ * Formats a user's info as log text. This is usually not needed because
+ * %L can be used to auto-format client information into a string.
+ *
+ * @param client Client index.
+ * @param buffer Buffer for text.
+ * @param maxlength Maximum length of text.
+ */
+stock FormatUserLogText(client, String:buffer[], maxlength)
+{
+ decl String:auth[32];
+ decl String:name[40];
+
+ new userid = GetClientUserId(client);
+ if (!GetClientAuthString(client, auth, sizeof(auth)))
+ {
+ strcopy(auth, sizeof(auth), "UNKNOWN");
+ }
+ if (!GetClientName(client, name, sizeof(name)))
+ {
+ strcopy(name, sizeof(name), "UNKNOWN");
+ }
+
+ /** Currently, no team stuff ... */
+
+ Format(buffer, maxlength, "\"%s<%d><%s><>\"", name, userid, auth);
+}
+
+/**
+ * Returns plugin handle from plugin filename.
+ *
+ * @param filename Filename of the plugin to search for.
+ * @return Handle to plugin if found, INVALID_HANDLE otherwise.
+ */
+stock Handle:FindPluginByFile(const String:filename[])
+{
+ decl String:buffer[256];
+
+ new Handle:iter = GetPluginIterator();
+ new Handle:pl;
+
+ while (MorePlugins(iter))
+ {
+ pl = ReadPlugin(iter);
+
+ GetPluginFilename(pl, buffer, sizeof(buffer));
+ if (strcmp(buffer, filename, false) == 0)
+ {
+ CloseHandle(iter);
+ return pl;
+ }
+ }
+
+ CloseHandle(iter);
+
+ return INVALID_HANDLE;
+}
+
+/**
+ * @deprecated Use FindTarget() or ProcessTargetString().
+ */
+#pragma deprecated Use FindTarget() or ProcessTargetString()
+stock SearchForClients(const String:pattern[], clients[], maxClients)
+{
+ new total = 0;
+
+ if (maxClients == 0)
+ {
+ return 0;
+ }
+
+ if (pattern[0] == '#')
+ {
+ new input = StringToInt(pattern[1]);
+ if (!input)
+ {
+ decl String:name[65]
+ for (new i=1; i<=MaxClients; i++)
+ {
+ if (!IsClientInGame(i))
+ {
+ continue;
+ }
+ GetClientName(i, name, sizeof(name));
+ if (strcmp(name, pattern, false) == 0)
+ {
+ clients[0] = i;
+ return 1;
+ }
+ }
+ } else {
+ new client = GetClientOfUserId(input);
+ if (client)
+ {
+ clients[0] = client;
+ return 1;
+ }
+ }
+ }
+
+ decl String:name[65]
+ for (new i=1; i<=MaxClients; i++)
+ {
+ if (!IsClientInGame(i))
+ {
+ continue;
+ }
+ GetClientName(i, name, sizeof(name));
+ if (StrContains(name, pattern, false) != -1)
+ {
+ clients[total++] = i;
+ if (total >= maxClients)
+ {
+ break;
+ }
+ }
+ }
+
+ return total;
+}
+
+/**
+ * Wraps ProcessTargetString() and handles producing error messages for
+ * bad targets.
+ *
+ * @param client Client who issued command
+ * @param target Client's target argument
+ * @param nobots Optional. Set to true if bots should NOT be targetted
+ * @param immunity Optional. Set to false to ignore target immunity.
+ * @return Index of target client, or -1 on error.
+ */
+stock FindTarget(client, const String:target[], bool:nobots = false, bool:immunity = true)
+{
+ decl String:target_name[MAX_TARGET_LENGTH];
+ decl target_list[1], target_count, bool:tn_is_ml;
+
+ new flags = COMMAND_FILTER_NO_MULTI;
+ if (nobots)
+ {
+ flags |= COMMAND_FILTER_NO_BOTS;
+ }
+ if (!immunity)
+ {
+ flags |= COMMAND_FILTER_NO_IMMUNITY;
+ }
+
+ if ((target_count = ProcessTargetString(
+ target,
+ client,
+ target_list,
+ 1,
+ flags,
+ target_name,
+ sizeof(target_name),
+ tn_is_ml)) > 0)
+ {
+ return target_list[0];
+ }
+ else
+ {
+ ReplyToTargetError(client, target_count);
+ return -1;
+ }
+}
+
+/**
+ * This function is no longer supported. It has been replaced with ReadMapList(),
+ * which uses a more unified caching and configuration mechanism. This function also
+ * has a bug where if the cvar contents changes, the fileTime change won't be recognized.
+ *
+ * Loads a specified array with maps. The maps will be either loaded from mapcyclefile, or if supplied
+ * a cvar containing a file name. If the file in the cvar is bad, it will use mapcyclefile. The fileTime
+ * parameter is used to store a timestamp of the file. If specified, the file will only be reloaded if it
+ * has changed.
+ *
+ * @param array Valid array handle, should be created with CreateArray(33) or larger.
+ * @param fileTime Variable containing the "last changed" time of the file. Used to avoid needless reloading.
+ * @param fileCvar CVAR set to the file to be loaded. Optional.
+ * @return Number of maps loaded or 0 if in error.
+ */
+#pragma deprecated Use ReadMapList() instead.
+ stock LoadMaps(Handle:array, &fileTime = 0, Handle:fileCvar = INVALID_HANDLE)
+ {
+ decl String:mapPath[256], String:mapFile[64];
+ new bool:fileFound = false;
+
+ if (fileCvar != INVALID_HANDLE)
+ {
+ GetConVarString(fileCvar, mapFile, 64);
+ BuildPath(Path_SM, mapPath, sizeof(mapPath), mapFile);
+ fileFound = FileExists(mapPath);
+ }
+
+ if (!fileFound)
+ {
+ new Handle:mapCycleFile = FindConVar("mapcyclefile");
+ GetConVarString(mapCycleFile, mapPath, sizeof(mapPath));
+ fileFound = FileExists(mapPath);
+ }
+
+ if (!fileFound)
+ {
+ LogError("Failed to find a file to load maps from. No maps loaded.");
+ ClearArray(array);
+
+ return 0;
+ }
+
+ // If the file hasn't changed, there's no reason to reload
+ // all of the maps.
+ new newTime = GetFileTime(mapPath, FileTime_LastChange);
+ if (fileTime == newTime)
+ {
+ return GetArraySize(array);
+ }
+
+ fileTime = newTime;
+
+ ClearArray(array);
+
+ new Handle:file = OpenFile(mapPath, "rt");
+ if (file == INVALID_HANDLE)
+ {
+ LogError("Could not open file: %s", mapPath);
+
+ return 0;
+ }
+
+ LogMessage("Loading maps from file: %s", mapPath);
+
+ decl String:buffer[64], len;
+ while (!IsEndOfFile(file) && ReadFileLine(file, buffer, sizeof(buffer)))
+ {
+ TrimString(buffer);
+
+ if ((len = StrContains(buffer, ".bsp", false)) != -1)
+ {
+ buffer[len] = '\0';
+ }
+
+ if (buffer[0] == '\0' || !IsValidConVarChar(buffer[0]) || !IsMapValid(buffer))
+ {
+ continue;
+ }
+
+ if (FindStringInArray(array, buffer) != -1)
+ {
+ continue;
+ }
+
+ PushArrayString(array, buffer);
+ }
+
+ CloseHandle(file);
+ return GetArraySize(array);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/keyvalues.inc b/sourcemod-1.5-dev/scripting/include/keyvalues.inc
new file mode 100644
index 0000000..51f6580
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/keyvalues.inc
@@ -0,0 +1,429 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _keyvalues_included
+ #endinput
+#endif
+#define _keyvalues_included
+
+/**
+ * KeyValue data value types
+ */
+enum KvDataTypes
+{
+ KvData_None = 0, /**< Type could not be identified, or no type */
+ KvData_String, /**< String value */
+ KvData_Int, /**< Integer value */
+ KvData_Float, /**< Floating point value */
+ KvData_Ptr, /**< Pointer value (sometimes called "long") */
+ KvData_WString, /**< Wide string value */
+ KvData_Color, /**< Color value */
+ KvData_UInt64, /**< Large integer value */
+ /* --- */
+ KvData_NUMTYPES,
+};
+
+/**
+ * Creates a new KeyValues structure. The Handle must always be closed.
+ *
+ * @param name Name of the root section.
+ * @param firstKey If non-empty, specifies the first key value.
+ * @param firstValue If firstKey is non-empty, specifies the first key's value.
+ * @return A Handle to a new KeyValues structure.
+ */
+native Handle:CreateKeyValues(const String:name[], const String:firstKey[]="", const String:firstValue[]="");
+
+/**
+ * Sets a string value of a KeyValues key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key, or NULL_STRING.
+ * @param value String value.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvSetString(Handle:kv, const String:key[], const String:value[]);
+
+/**
+ * Sets an integer value of a KeyValues key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key, or NULL_STRING.
+ * @param value Value number.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvSetNum(Handle:kv, const String:key[], value);
+
+/**
+ * Sets a large integer value of a KeyValues key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key, or NULL_STRING.
+ * @param value Large integer value (0=High bits, 1=Low bits)
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvSetUInt64(Handle:kv, const String:key[], const value[2]);
+
+/**
+ * Sets a floating point value of a KeyValues key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key, or NULL_STRING.
+ * @param value Floating point value.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvSetFloat(Handle:kv, const String:key[], Float:value);
+
+/**
+ * Sets a set of color values of a KeyValues key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key, or NULL_STRING.
+ * @param r Red value.
+ * @param g Green value.
+ * @param b Blue value.
+ * @param a Alpha value.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvSetColor(Handle:kv, const String:key[], r, g, b, a=0);
+
+/**
+ * Sets a vector value of a KeyValues key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key, or NULL_STRING.
+ * @param vec Vector value.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvSetVector(Handle:kv, const String:key[], const Float:vec[3]);
+
+/**
+ * Retrieves a string value from a KeyValues key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key, or NULL_STRING.
+ * @param value Buffer to store key value in.
+ * @param maxlength Maximum length of the value buffer.
+ * @param defvalue Optional default value to use if the key is not found.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvGetString(Handle:kv, const String:key[], String:value[], maxlength, const String:defvalue[]="");
+
+/**
+ * Retrieves an integer value from a KeyValues key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key, or NULL_STRING.
+ * @param defvalue Optional default value to use if the key is not found.
+ * @return Integer value of the key.
+ * @error Invalid Handle.
+ */
+native KvGetNum(Handle:kv, const String:key[], defvalue=0);
+
+/**
+ * Retrieves a floating point value from a KeyValues key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key, or NULL_STRING.
+ * @param defvalue Optional default value to use if the key is not found.
+ * @return Floating point value of the key.
+ * @error Invalid Handle.
+ */
+native Float:KvGetFloat(Handle:kv, const String:key[], Float:defvalue=0.0);
+
+/**
+ * Retrieves a set of color values from a KeyValues key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key, or NULL_STRING.
+ * @param r Red value, set by reference.
+ * @param g Green value, set by reference.
+ * @param b Blue value, set by reference.
+ * @param a Alpha value, set by reference.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvGetColor(Handle:kv, const String:key[], &r, &g, &b, &a);
+
+/**
+ * Retrieves a large integer value from a KeyValues key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key, or NULL_STRING.
+ * @param value Array to represent the large integer.
+ * @param defvalue Optional default value to use if the key is not found.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvGetUInt64(Handle:kv, const String:key[], value[2], defvalue[2]={0,0});
+
+/**
+ * Retrieves a vector value from a KeyValues key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key, or NULL_STRING.
+ * @param vec Destination vector to store the value in.
+ * @param defvalue Optional default value to use if the key is not found.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvGetVector(Handle:kv, const String:key[], Float:vec[3], const Float:defvalue[3]={0.0, 0.0, 0.0});
+
+/**
+ * Sets the current position in the KeyValues tree to the given key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key.
+ * @param create If true, and the key does not exist, it will be created.
+ * @return True if the key exists, false if it does not and was not created.
+ */
+native bool:KvJumpToKey(Handle:kv, const String:key[], bool:create=false);
+
+/**
+ * Sets the current position in the KeyValues tree to the given key.
+ *
+ * @param kv KeyValues Handle.
+ * @param id KeyValues id.
+ * @return True if the key exists, false if it does not.
+ */
+native bool:KvJumpToKeySymbol(Handle:kv, id);
+
+/**
+ * Sets the current position in the KeyValues tree to the first sub key.
+ * This native adds to the internal traversal stack.
+ *
+ * @param kv KeyValues Handle.
+ * @param keyOnly If false, non-keys will be traversed (values).
+ * @return True on success, false if there was no first sub key.
+ * @error Invalid Handle.
+ */
+native bool:KvGotoFirstSubKey(Handle:kv, bool:keyOnly=true);
+
+/**
+ * Sets the current position in the KeyValues tree to the next sub key.
+ * This native does NOT add to the internal traversal stack, and thus
+ * KvGoBack() is not needed for each successive call to this function.
+ *
+ * @param kv KeyValues Handle.
+ * @param keyOnly If false, non-keys will be traversed (values).
+ * @return True on success, false if there was no next sub key.
+ * @error Invalid Handle.
+ */
+native bool:KvGotoNextKey(Handle:kv, bool:keyOnly=true);
+
+/**
+ * Saves the current position in the traversal stack onto the traversal
+ * stack. This can be useful if you wish to use KvGotoNextKey() and
+ * have the previous key saved for backwards traversal.
+ *
+ * @param kv KeyValues Handle.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvSavePosition(Handle:kv);
+
+/**
+ * Removes the given key from the current position.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Name of the key.
+ * @return True on success, false if key did not exist.
+ * @error Invalid Handle.
+ */
+native bool:KvDeleteKey(Handle:kv, const String:key[]);
+
+/**
+ * Removes the current sub-key and attempts to set the position
+ * to the sub-key after the removed one. If no such sub-key exists,
+ * the position will be the parent key in the traversal stack.
+ * Given the sub-key having position "N" in the traversal stack, the
+ * removal will always take place from position "N-1."
+ *
+ * @param kv KeyValues Handle.
+ * @return 1 if removal succeeded and there was another key.
+ * 0 if the current node was not contained in the
+ * previous node, or no previous node exists.
+ * -1 if removal succeeded and there were no more keys,
+ * thus the state is as if KvGoBack() was called.
+ * @error Invalid Handle.
+ */
+native KvDeleteThis(Handle:kv);
+
+/**
+ * Jumps back to the previous position. Returns false if there are no
+ * previous positions (i.e., at the root node). This should be called
+ * once for each successful Jump call, in order to return to the top node.
+ * This function pops one node off the internal traversal stack.
+ *
+ * @param kv KeyValues Handle.
+ * @return True on success, false if there is no higher node.
+ * @error Invalid Handle.
+ */
+native bool:KvGoBack(Handle:kv);
+
+/**
+ * Sets the position back to the top node, emptying the entire node
+ * traversal history. This can be used instead of looping KvGoBack()
+ * if recursive iteration is not important.
+ *
+ * @param kv KeyValues Handle.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvRewind(Handle:kv);
+
+/**
+ * Retrieves the current section name.
+ *
+ * @param kv KeyValues Handle.
+ * @param section Buffer to store the section name.
+ * @param maxlength Maximum length of the name buffer.
+ * @return True on success, false on failure.
+ * @error Invalid Handle.
+ */
+native bool:KvGetSectionName(Handle:kv, String:section[], maxlength);
+
+/**
+ * Sets the current section name.
+ *
+ * @param kv KeyValues Handle.
+ * @param section Section name.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvSetSectionName(Handle:kv, const String:section[]);
+
+/**
+ * Returns the data type at a key.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Key name.
+ * @return KvDataType value of the key.
+ * @error Invalid Handle.
+ */
+native KvDataTypes:KvGetDataType(Handle:kv, const String:key[]);
+
+/**
+ * Converts a KeyValues tree to a file. The tree is dumped
+ * from the current position.
+ *
+ * @param kv KeyValues Handle.
+ * @param file File to dump write to.
+ * @return True on success, false otherwise.
+ * @error Invalid Handle.
+ */
+native bool:KeyValuesToFile(Handle:kv, const String:file[]);
+
+/**
+ * Converts a file to a KeyValues tree. The file is read into
+ * the current position of the tree.
+ *
+ * @param kv KeyValues Handle.
+ * @param file File to read from.
+ * @return True on success, false otherwise.
+ * @error Invalid Handle.
+ */
+native bool:FileToKeyValues(Handle:kv, const String:file[]);
+
+/**
+ * Sets whether or not the KeyValues parser will read escape sequences.
+ * For example, \n would be read as a literal newline. This defaults
+ * to false for new KeyValues structures.
+ *
+ * @param kv KeyValues Handle.
+ * @param useEscapes Whether or not to read escape sequences.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvSetEscapeSequences(Handle:kv, bool:useEscapes);
+
+/**
+ * Returns the position in the jump stack; I.e. the number of calls
+ * required for KvGoBack to return to the root node. If at the root node,
+ * 0 is returned.
+ *
+ * @param kv KeyValues Handle.
+ * @return Number of non-root nodes in the jump stack.
+ * @error Invalid Handle.
+ */
+native KvNodesInStack(Handle:kv);
+
+/**
+ * Makes a new copy of all subkeys in the origin KeyValues to
+ * the destination KeyValues.
+ * NOTE: All KeyValues are processed from the current location not the root one.
+ *
+ * @param origin Origin KeyValues Handle.
+ * @param dest Destination KeyValues Handle.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native KvCopySubkeys(Handle:origin, Handle:dest);
+
+/**
+ * Finds a KeyValues name by id.
+ *
+ * @param kv KeyValues Handle.
+ * @param id KeyValues id.
+ * @param name Buffer to store the name.
+ * @param maxlength Maximum length of the value buffer.
+ * @return True on success, false if id not found.
+ * @error Invalid Handle.
+ */
+native bool:KvFindKeyById(Handle:kv, id, String:name[], maxlength);
+
+/**
+ * Finds a KeyValues id inside a KeyValues tree.
+ *
+ * @param kv KeyValues Handle.
+ * @param key Key name.
+ * @param id Id of the found KeyValue.
+ * @return True on success, false if key not found.
+ * @error Invalid Handle.
+ */
+native bool:KvGetNameSymbol(Handle:kv, const String:key[], &id);
+
+/**
+ * Retrieves the current section id.
+ *
+ * @param kv KeyValues Handle.
+ * @param id Id of the current section.
+ * @return True on success, false on failure.
+ * @error Invalid Handle.
+ */
+native bool:KvGetSectionSymbol(Handle:kv, &id);
diff --git a/sourcemod-1.5-dev/scripting/include/lang.inc b/sourcemod-1.5-dev/scripting/include/lang.inc
new file mode 100644
index 0000000..6ff4464
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/lang.inc
@@ -0,0 +1,121 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _lang_included
+ #endinput
+#endif
+#define _lang_included
+
+#define LANG_SERVER 0 /**< Translate using the server's language */
+
+/**
+ * Loads a translation file for the plugin calling this native.
+ * If no extension is specified, .txt is assumed.
+ *
+ * @param file Translation file.
+ * @noreturn
+ */
+native LoadTranslations(const String:file[]);
+
+/**
+ * Sets the global language target. This is useful for creating functions
+ * that will be compatible with the %t format specifier. Note that invalid
+ * indexes can be specified but the error will occur during translation,
+ * not during this function call.
+ *
+ * @param client Client index or LANG_SERVER.
+ * @noreturn
+ */
+native SetGlobalTransTarget(client);
+
+/**
+ * Retrieves the language number of a client.
+ * Currently this simply returns the server language index.
+ *
+ * @param client Client index.
+ * @return Language number client is using.
+ * @error Invalid client index or client not connected.
+ */
+native GetClientLanguage(client);
+
+/**
+ * Retrieves the server's language.
+ *
+ * @return Language number server is using.
+ */
+native GetServerLanguage();
+
+/**
+ * Returns the number of languages known in languages.cfg.
+ *
+ * @return Language count.
+ */
+native GetLanguageCount();
+
+/**
+ * Retrieves info about a given language number.
+ *
+ * @param language Language number.
+ * @param code Language code buffer (2-3 characters usually).
+ * @param codeLen Maximum length of the language code buffer.
+ * @param name Language name buffer.
+ * @param nameLen Maximum length of the language name buffer.
+ * @noreturn
+ * @error Invalid language number.
+ */
+native GetLanguageInfo(language, String:code[]="", codeLen=0, String:name[]="", nameLen=0);
+
+/**
+ * Sets the language number of a client.
+ *
+ * @param client Client index.
+ * @param language Language number.
+ * @noreturn
+ * @error Invalid client index or client not connected.
+ */
+native SetClientLanguage(client, language);
+
+/**
+ * Retrieves the language number from a language code.
+ *
+ * @param code Language code (2-3 characters usually).
+ * @return Language number. -1 if not found.
+ */
+native GetLanguageByCode(const String:code[]);
+
+/**
+ * Retrieves the language number from a language name.
+ *
+ * @param name Language name (case insensitive).
+ * @return Language number. -1 if not found.
+ */
+native GetLanguageByName(const String:name[]);
diff --git a/sourcemod-1.5-dev/scripting/include/logging.inc b/sourcemod-1.5-dev/scripting/include/logging.inc
new file mode 100644
index 0000000..4269b22
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/logging.inc
@@ -0,0 +1,142 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sm_logging_included
+ #endinput
+#endif
+#define _sm_logging_included
+
+/**
+ * Logs a plugin message to the SourceMod logs. The log message will be
+ * prefixed by the plugin's logtag (filename).
+ *
+ * @param format String format.
+ * @param ... Format arguments.
+ * @noreturn
+ */
+native LogMessage(const String:format[], any:...);
+
+/**
+ * Logs a message to any file. The log message will be in the normal
+ * SourceMod format, with the plugin logtag prepended.
+ *
+ * @param file File to write the log message in.
+ * @param format String format.
+ * @param ... Format arguments.
+ * @noreturn
+ * @error File could not be opened/written.
+ */
+native LogToFile(const String:file[], const String:format[], any:...);
+
+/**
+ * Same as LogToFile(), except no plugin logtag is prepended.
+ *
+ * @param file File to write the log message in.
+ * @param format String format.
+ * @param ... Format arguments.
+ * @noreturn
+ * @error File could not be opened/written.
+ */
+native LogToFileEx(const String:file[], const String:format[], any:...);
+
+/**
+ * Logs an action from a command or event whereby interception and routing may
+ * be important. This is intended to be a logging version of ShowActivity().
+ *
+ * @param client Client performing the action, 0 for server, or -1 if not
+ * applicable.
+ * @param target Client being targetted, or -1 if not applicable.
+ * @param message Message format.
+ * @param ... Message formatting parameters.
+ * @noreturn
+ */
+native LogAction(client, target, const String:message[], any:...);
+
+/**
+ * Logs a plugin error message to the SourceMod logs.
+ *
+ * @param format String format.
+ * @param ... Format arguments.
+ * @noreturn
+ */
+native LogError(const String:format[], any:...);
+
+/**
+ * Called when an action is going to be logged.
+ *
+ * @param source Handle to the object logging the action, or INVALID_HANDLE
+ * if Core is logging the action.
+ * @param ident Type of object logging the action (plugin, ext, or core).
+ * @param client Client the action is from; 0 for server, -1 if not applicable.
+ * @param target Client the action is targetting, or -1 if not applicable.
+ * @param message Message that is being logged.
+ * @return Plugin_Continue will cause Core to defaulty log the message.
+ * Plugin_Handled will stop Core from logging the message.
+ * Plugin_Stop is the same as Handled, but prevents any other
+ * plugins from handling the message.
+ */
+forward Action:OnLogAction(Handle:source,
+ Identity:ident,
+ client,
+ target,
+ const String:message[]);
+
+/**
+ * Called when a game log message is received.
+ *
+ * Any Log*() functions called within this callback will not recursively
+ * pass through. That is, they will log directly, bypassing this callback.
+ *
+ * Note that this does not capture log messages from the engine. It only
+ * captures log messages being sent from the game/mod itself.
+ *
+ * @param message Message contents.
+ * @return Plugin_Handled or Plugin_Stop will prevent the message
+ * from being written to the log file.
+ */
+functag public Action:GameLogHook(const String:message[]);
+
+/**
+ * Adds a game log hook.
+ *
+ * @param hook Hook function.
+ * @noreturn
+ */
+native AddGameLogHook(GameLogHook:hook);
+
+/**
+ * Removes a game log hook.
+ *
+ * @param hook Hook function.
+ * @noreturn
+ */
+native RemoveGameLogHook(GameLogHook:hook);
diff --git a/sourcemod-1.5-dev/scripting/include/mapchooser.inc b/sourcemod-1.5-dev/scripting/include/mapchooser.inc
new file mode 100644
index 0000000..0e9e73c
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/mapchooser.inc
@@ -0,0 +1,132 @@
+#if defined _mapchooser_included_
+ #endinput
+#endif
+#define _mapchooser_included_
+
+enum NominateResult
+{
+ Nominate_Added, /** The map was added to the nominate list */
+ Nominate_Replaced, /** A clients existing nomination was replaced */
+ Nominate_AlreadyInVote, /** Specified map was already in the vote */
+ Nominate_InvalidMap, /** Mapname specifed wasn't a valid map */
+ Nominate_VoteFull, /** This will only occur if force was set to false */
+};
+
+enum MapChange
+{
+ MapChange_Instant, /** Change map as soon as the voting results have come in */
+ MapChange_RoundEnd, /** Change map at the end of the round */
+ MapChange_MapEnd, /** Change the sm_nextmap cvar */
+};
+
+/**
+ * Attempt to add a map to the mapchooser map list.
+ *
+ * @param map Map to add.
+ * @param force Should we force the map in even if it requires overwriting an existing nomination?
+ * @param owner Client index of the nominater. If the client disconnects the nomination will be removed. Use 0 for constant nominations
+ * @return Nominate Result of the outcome
+ */
+native NominateResult:NominateMap(const String:map[], bool:force, owner);
+
+/**
+ * Attempt to remove a map from the mapchooser map list.
+ *
+ * @param map Map to remove.
+ * @return True if the nomination was found and removed, or false if the nomination was not found.
+ */
+native bool:RemoveNominationByMap(const String:map[]);
+
+/**
+ * Attempt to remove a map from the mapchooser map list.
+ *
+ * @param owner Client index of the nominater.
+ * @return True if the nomination was found and removed, or false if the nomination was not found.
+ */
+native bool:RemoveNominationByOwner(owner);
+
+/**
+ * Gets the current list of excluded maps.
+ *
+ * @param array An ADT array handle to add the map strings to.
+ * @noreturn
+ */
+native GetExcludeMapList(Handle:array);
+
+/**
+ * Gets the current list of nominated maps.
+ *
+ * @param maparray An ADT array handle to add the map strings to.
+ * @param ownerarray An optional ADT array handle to add the nominator client indexes to.
+ * @noreturn
+ */
+native GetNominatedMapList(Handle:maparray, Handle:ownerarray = INVALID_HANDLE);
+
+/**
+ * Checks if MapChooser will allow a vote
+ *
+ * @return True if a vote can be held, or false if mapchooser is already holding a vote.
+ */
+native bool:CanMapChooserStartVote();
+
+/**
+ * Initiates a MapChooser map vote
+ *
+ * Note: If no input array is specified mapchooser will use its internal list. This includes
+ * any nominations and excluded maps (as per mapchoosers convars).
+ *
+ * @param when MapChange consant of when the resulting mapchange should occur.
+ * @param inputarray ADT array list of maps to add to the vote.
+ */
+native InitiateMapChooserVote(MapChange:when, Handle:inputarray=INVALID_HANDLE);
+
+/**
+ * Checks if MapChooser's end of map vote has completed.
+ *
+ * @return True if complete, false otherwise.
+ */
+native bool:HasEndOfMapVoteFinished();
+
+/**
+ * Checks if MapChooser is set to run an end of map vote.
+ *
+ * @return True if enabled, false otherwise.
+ */
+native bool:EndOfMapVoteEnabled();
+
+/**
+ * Called when mapchooser removes a nomination from its list.
+ * Nominations cleared on map start will not trigger this forward
+ */
+forward OnNominationRemoved(const String:map[], owner);
+
+/**
+ * Called when mapchooser starts a Map Vote.
+ */
+forward OnMapVoteStarted();
+
+
+public SharedPlugin:__pl_mapchooser =
+{
+ name = "mapchooser",
+ file = "mapchooser.smx",
+#if defined REQUIRE_PLUGIN
+ required = 1,
+#else
+ required = 0,
+#endif
+};
+
+public __pl_mapchooser_SetNTVOptional()
+{
+ MarkNativeAsOptional("NominateMap");
+ MarkNativeAsOptional("RemoveNominationByMap");
+ MarkNativeAsOptional("RemoveNominationByOwner");
+ MarkNativeAsOptional("GetExcludeMapList");
+ MarkNativeAsOptional("GetNominatedMapList");
+ MarkNativeAsOptional("CanMapChooserStartVote");
+ MarkNativeAsOptional("InitiateMapChooserVote");
+ MarkNativeAsOptional("HasEndOfMapVoteFinished");
+ MarkNativeAsOptional("EndOfMapVoteEnabled");
+}
+
diff --git a/sourcemod-1.5-dev/scripting/include/menus.inc b/sourcemod-1.5-dev/scripting/include/menus.inc
new file mode 100644
index 0000000..fa6cbac
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/menus.inc
@@ -0,0 +1,827 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _menus_included
+ #endinput
+#endif
+#define _menus_included
+
+/**
+ * Low-level drawing style of the menu.
+ */
+enum MenuStyle
+{
+ MenuStyle_Default = 0, /**< The "default" menu style for the mod */
+ MenuStyle_Valve = 1, /**< The Valve provided menu style (Used on HL2DM) */
+ MenuStyle_Radio = 2, /**< The simpler menu style commonly used on CS:S */
+};
+
+/**
+ * Different actions for the menu "pump" callback
+ */
+enum MenuAction
+{
+ MenuAction_Start = (1<<0), /**< A menu has been started (nothing passed) */
+ MenuAction_Display = (1<<1), /**< A menu is about to be displayed (param1=client, param2=MenuPanel Handle) */
+ MenuAction_Select = (1<<2), /**< An item was selected (param1=client, param2=item) */
+ MenuAction_Cancel = (1<<3), /**< The menu was cancelled (param1=client, param2=reason) */
+ MenuAction_End = (1<<4), /**< A menu display has fully ended.
+ param1 is the MenuEnd reason, and if it's MenuEnd_Cancelled, then
+ param2 is the MenuCancel reason from MenuAction_Cancel.
+ */
+ MenuAction_VoteEnd = (1<<5), /**< (VOTE ONLY): A vote sequence has succeeded (param1=chosen item)
+ This is not called if SetVoteResultCallback has been used on the menu. */
+ MenuAction_VoteStart = (1<<6), /**< (VOTE ONLY): A vote sequence has started (nothing passed) */
+ MenuAction_VoteCancel = (1<<7), /**< (VOTE ONLY): A vote sequence has been cancelled (param1=reason) */
+ MenuAction_DrawItem = (1<<8), /**< An item is being drawn; return the new style (param1=client, param2=item) */
+ MenuAction_DisplayItem = (1<<9),/**< Item text is being drawn to the display (param1=client, param2=item)
+ To change the text, use RedrawMenuItem().
+ If you do so, return its return value. Otherwise, return 0.
+ */
+};
+
+/** Default menu actions */
+#define MENU_ACTIONS_DEFAULT MenuAction_Select|MenuAction_Cancel|MenuAction_End
+/** All menu actions */
+#define MENU_ACTIONS_ALL MenuAction:0xFFFFFFFF
+
+#define MENU_NO_PAGINATION 0 /**< Menu should not be paginated (10 items max) */
+#define MENU_TIME_FOREVER 0 /**< Menu should be displayed as long as possible */
+
+#define ITEMDRAW_DEFAULT (0) /**< Item should be drawn normally */
+#define ITEMDRAW_DISABLED (1<<0) /**< Item is drawn but not selectable */
+#define ITEMDRAW_RAWLINE (1<<1) /**< Item should be a raw line, without a slot */
+#define ITEMDRAW_NOTEXT (1<<2) /**< No text should be drawn */
+#define ITEMDRAW_SPACER (1<<3) /**< Item should be drawn as a spacer, if possible */
+#define ITEMDRAW_IGNORE ((1<<1)|(1<<2)) /**< Item should be completely ignored (rawline + notext) */
+#define ITEMDRAW_CONTROL (1<<4) /**< Item is control text (back/next/exit) */
+
+#define MENUFLAG_BUTTON_EXIT (1<<0) /**< Menu has an "exit" button (default if paginated) */
+#define MENUFLAG_BUTTON_EXITBACK (1<<1) /**< Menu has an "exit back" button */
+#define MENUFLAG_NO_SOUND (1<<2) /**< Menu will not have any select sounds */
+#define MENUFLAG_BUTTON_NOVOTE (1<<3) /**< Menu has a "No Vote" button at slot 1 */
+
+#define VOTEINFO_CLIENT_INDEX 0 /**< Client index */
+#define VOTEINFO_CLIENT_ITEM 1 /**< Item the client selected, or -1 for none */
+#define VOTEINFO_ITEM_INDEX 0 /**< Item index */
+#define VOTEINFO_ITEM_VOTES 1 /**< Number of votes for the item */
+
+#define VOTEFLAG_NO_REVOTES (1<<0) /**< Players cannot change their votes */
+
+/**
+ * Reasons a menu can be cancelled (MenuAction_Cancel).
+ */
+enum
+{
+ MenuCancel_Disconnected = -1, /**< Client dropped from the server */
+ MenuCancel_Interrupted = -2, /**< Client was interrupted with another menu */
+ MenuCancel_Exit = -3, /**< Client exited via "exit" */
+ MenuCancel_NoDisplay = -4, /**< Menu could not be displayed to the client */
+ MenuCancel_Timeout = -5, /**< Menu timed out */
+ MenuCancel_ExitBack = -6, /**< Client selected "exit back" on a paginated menu */
+};
+
+/**
+ * Reasons a vote can be cancelled (MenuAction_VoteCancel).
+ */
+enum
+{
+ VoteCancel_Generic = -1, /**< Vote was generically cancelled. */
+ VoteCancel_NoVotes = -2, /**< Vote did not receive any votes. */
+};
+
+/**
+ * Reasons a menu ended (MenuAction_End).
+ */
+enum
+{
+ MenuEnd_Selected = 0, /**< Menu item was selected */
+ MenuEnd_VotingDone = -1, /**< Voting finished */
+ MenuEnd_VotingCancelled = -2, /**< Voting was cancelled */
+ MenuEnd_Cancelled = -3, /**< Menu was cancelled (reason in param2) */
+ MenuEnd_Exit = -4, /**< Menu was cleanly exited via "exit" */
+ MenuEnd_ExitBack = -5, /**< Menu was cleanly exited via "back" */
+};
+
+/**
+ * Describes a menu's source
+ */
+enum MenuSource
+{
+ MenuSource_None = 0, /**< No menu is being displayed */
+ MenuSource_External = 1, /**< External menu */
+ MenuSource_Normal = 2, /**< A basic menu is being displayed */
+ MenuSource_RawPanel = 3, /**< A display is active, but it is not tied to a menu */
+};
+
+/**
+ * Called when a menu action is completed.
+ *
+ * @param menu The menu being acted upon.
+ * @param action The action of the menu.
+ * @param param1 First action parameter (usually the client).
+ * @param param2 Second action parameter (usually the item).
+ * @noreturn
+ */
+functag public MenuHandler(Handle:menu, MenuAction:action, param1, param2);
+
+/**
+ * Creates a new, empty menu using the default style.
+ *
+ * @param handler Function which will receive menu actions.
+ * @param actions Optionally set which actions to receive. Select,
+ * Cancel, and End will always be received regardless
+ * of whether they are set or not. They are also
+ * the only default actions.
+ * @return A new menu Handle.
+ */
+native Handle:CreateMenu(MenuHandler:handler, MenuAction:actions=MENU_ACTIONS_DEFAULT);
+
+/**
+ * Displays a menu to a client.
+ *
+ * @param menu Menu Handle.
+ * @param client Client index.
+ * @param time Maximum time to leave menu on the screen.
+ * @return True on success, false on failure.
+ * @error Invalid Handle or client not in game.
+ */
+native bool:DisplayMenu(Handle:menu, client, time);
+
+/**
+ * Displays a menu to a client, starting from the given item.
+ *
+ * @param menu Menu Handle.
+ * @param client Client index.
+ * @param first_item First item to begin drawing from.
+ * @param time Maximum time to leave menu on the screen.
+ * @return True on success, false on failure.
+ * @error Invalid Handle or client not in game.
+ */
+native bool:DisplayMenuAtItem(Handle:menu, client, first_item, time);
+
+/**
+ * Appends a new item to the end of a menu.
+ *
+ * @param menu Menu Handle.
+ * @param info Item information string.
+ * @param display Default item display string.
+ * @param style Drawing style flags. Anything other than DEFAULT or
+ * DISABLED will be completely ignored when paginating.
+ * @return True on success, false on failure.
+ * @error Invalid Handle or item limit reached.
+ */
+native AddMenuItem(Handle:menu,
+ const String:info[],
+ const String:display[],
+ style=ITEMDRAW_DEFAULT);
+
+/**
+ * Inserts an item into the menu before a certain position; the new item will
+ * be at the given position and all next items pushed forward.
+ *
+ * @param menu Menu Handle.
+ * @param position Position, starting from 0.
+ * @param info Item information string.
+ * @param display Default item display string.
+ * @param style Drawing style flags. Anything other than DEFAULT or
+ * DISABLED will be completely ignored when paginating.
+ * @return True on success, false on failure.
+ * @error Invalid Handle or menu position.
+ */
+native bool:InsertMenuItem(Handle:menu,
+ position,
+ const String:info[],
+ const String:display[],
+ style=ITEMDRAW_DEFAULT);
+
+/**
+ * Removes an item from the menu.
+ *
+ * @param menu Menu Handle.
+ * @param position Position, starting from 0.
+ * @return True on success, false on failure.
+ * @error Invalid Handle or menu position.
+ */
+native bool:RemoveMenuItem(Handle:menu, position);
+
+/**
+ * Removes all items from a menu.
+ *
+ * @param menu Menu Handle.
+ * @noreturn
+ * @error Invalid Handle or menu position.
+ */
+native RemoveAllMenuItems(Handle:menu);
+
+/**
+ * Retrieves information about a menu item.
+ *
+ * @param menu Menu Handle.
+ * @param position Position, starting from 0.
+ * @param infoBuf Info buffer.
+ * @param infoBufLen Maximum length of the info buffer.
+ * @param style By-reference variable to store drawing flags.
+ * @param dispBuf Display buffer.
+ * @param dispBufLen Maximum length of the display buffer.
+ * @return True on success, false if position is invalid.
+ * @error Invalid Handle.
+ */
+native bool:GetMenuItem(Handle:menu,
+ position,
+ String:infoBuf[],
+ infoBufLen,
+ &style=0,
+ String:dispBuf[]="",
+ dispBufLen=0);
+
+/**
+ * Returns the first item on the page of a currently selected menu.
+ *
+ * This is only valid inside a MenuAction_Select callback.
+ *
+ * @return First item number on the page the client was viewing
+ * before selecting the item in the callback. This can
+ * be used to re-display the menu from the original
+ * position.
+ * @error Not called from inside a MenuAction_Select callback.
+ */
+native GetMenuSelectionPosition();
+
+/**
+ * Returns the number of items in a menu.
+ *
+ * @param menu Menu Handle.
+ * @return Number of items in the menu.
+ * @error Invalid Handle.
+ */
+native GetMenuItemCount(Handle:menu);
+
+/**
+ * Sets whether the menu should be paginated or not.
+ *
+ * If itemsPerPage is MENU_NO_PAGINATION, and the exit button flag is set,
+ * then the exit button flag is removed. It can be re-applied if desired.
+ *
+ * @param menu Handle to the menu.
+ * @param itemsPerPage Number of items per page, or MENU_NO_PAGINATION.
+ * @return True on success, false if pagination is too high or
+ * low.
+ * @error Invalid Handle.
+ */
+native bool:SetMenuPagination(Handle:menu, itemsPerPage);
+
+/**
+ * Returns a menu's pagination setting.
+ *
+ * @param menu Handle to the menu.
+ * @return Pagination setting.
+ * @error Invalid Handle.
+ */
+native GetMenuPagination(Handle:menu);
+
+/**
+ * Returns a menu's MenuStyle Handle. The Handle
+ * is global and cannot be freed.
+ *
+ * @param menu Handle to the menu.
+ * @return Handle to the menu's draw style.
+ * @error Invalid Handle.
+ */
+native Handle:GetMenuStyle(Handle:menu);
+
+/**
+ * Sets the menu's default title/instruction message.
+ *
+ * @param menu Menu Handle.
+ * @param fmt Message string format
+ * @param ... Message string arguments.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native SetMenuTitle(Handle:menu, const String:fmt[], any:...);
+
+/**
+ * Returns the text of a menu's title.
+ *
+ * @param menu Menu Handle.
+ * @param buffer Buffer to store title.
+ * @param maxlength Maximum length of the buffer.
+ * @return Number of bytes written.
+ * @error Invalid Handle/
+ */
+native GetMenuTitle(Handle:menu, String:buffer[], maxlength);
+
+/**
+ * Creates a raw MenuPanel based off the menu's style.
+ * The Handle must be freed with CloseHandle().
+ *
+ * @param menu Menu Handle.
+ * @return A new MenuPanel Handle.
+ * @error Invalid Handle.
+ */
+native Handle:CreatePanelFromMenu(Handle:menu);
+
+/**
+ * Returns whether or not the menu has an exit button.
+ * By default, menus have an exit button.
+ *
+ * @param menu Menu Handle.
+ * @return True if the menu has an exit button; false otherwise.
+ * @error Invalid Handle.
+ */
+native bool:GetMenuExitButton(Handle:menu);
+
+/**
+ * Sets whether or not the menu has an exit button. By default, paginated menus
+ * have an exit button.
+ *
+ * If a menu's pagination is changed to MENU_NO_PAGINATION, and the pagination
+ * was previously a different value, then the Exit button status is changed to
+ * false. It must be explicitly re-enabled afterwards.
+ *
+ * If a non-paginated menu has an exit button, then at most 9 items will be
+ * displayed.
+ *
+ * @param menu Menu Handle.
+ * @param button True to enable the button, false to remove it.
+ * @return True if allowed; false on failure.
+ * @error Invalid Handle.
+ */
+native bool:SetMenuExitButton(Handle:menu, bool:button);
+
+/**
+ * Returns whether or not the menu has an "exit back" button. By default,
+ * menus do not have an exit back button.
+ *
+ * Exit Back buttons appear as "Back" on page 1 of paginated menus and have
+ * functionality defined by the user in MenuEnd_ExitBack.
+ *
+ * @param menu Menu Handle.
+ * @return True if the menu has an exit back button; false otherwise.
+ * @error Invalid Handle.
+ */
+native bool:GetMenuExitBackButton(Handle:menu);
+
+/**
+ * Sets whether or not the menu has an "exit back" button. By default, menus
+ * do not have an exit back button.
+ *
+ * Exit Back buttons appear as "Back" on page 1 of paginated menus and have
+ * functionality defined by the user in MenuEnd_ExitBack.
+ *
+ * @param menu Menu Handle.
+ * @param button True to enable the button, false to remove it.
+ * @error Invalid Handle.
+ */
+native SetMenuExitBackButton(Handle:menu, bool:button);
+
+/**
+ * Sets whether or not the menu has a "no vote" button in slot 1.
+ * By default, menus do not have a no vote button.
+ *
+ * @param menu Menu Handle.
+ * @param button True to enable the button, false to remove it.
+ * @return True if allowed; false on failure.
+ * @error Invalid Handle.
+ */
+native bool:SetMenuNoVoteButton(Handle:menu, bool:button);
+
+/**
+ * Cancels a menu from displaying on all clients. While the
+ * cancellation is in progress, this menu cannot be re-displayed
+ * to any clients.
+ *
+ * The menu may still exist on the client's screen after this command.
+ * This simply verifies that the menu is not being used anywhere.
+ *
+ * If any vote is in progress on a menu, it will be cancelled.
+ *
+ * @param menu Menu Handle.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native CancelMenu(Handle:menu);
+
+/**
+ * Retrieves a menu's option flags.
+ *
+ * @param menu Menu Handle.
+ * @return A bitstring of MENUFLAG bits.
+ * @error Invalid Handle.
+ */
+native GetMenuOptionFlags(Handle:menu);
+
+/**
+ * Sets a menu's option flags.
+ *
+ * If a certain bit is not supported, it will be stripped before being set.
+ * See SetMenuExitButton() for information on Exit buttons.
+ * See SetMenuExitBackButton() for information on Exit Back buttons.
+ *
+ * @param menu Menu Handle.
+ * @param flags A new bitstring of MENUFLAG bits.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native SetMenuOptionFlags(Handle:menu, flags);
+
+/**
+ * Returns whether a vote is in progress.
+ *
+ * @param menu Deprecated; no longer used.
+ * @return True if a vote is in progress, false otherwise.
+ */
+native bool:IsVoteInProgress(Handle:menu=INVALID_HANDLE);
+
+/**
+ * Cancels the vote in progress.
+ *
+ * @noreturn
+ * @error If no vote is in progress.
+ */
+native CancelVote();
+
+/**
+ * Broadcasts a menu to a list of clients. The most selected item will be
+ * returned through MenuAction_End. On a tie, a random item will be returned
+ * from a list of the tied items.
+ *
+ * Note that MenuAction_VoteEnd and MenuAction_VoteStart are both
+ * default callbacks and do not need to be enabled.
+ *
+ * @param menu Menu Handle.
+ * @param clients Array of clients to broadcast to.
+ * @param numClients Number of clients in the array.
+ * @param time Maximum time to leave menu on the screen.
+ * @param flags Optional voting flags.
+ * @return True on success, false if this menu already has a vote session
+ * in progress.
+ * @error Invalid Handle, or a vote is already in progress.
+ */
+native bool:VoteMenu(Handle:menu, clients[], numClients, time, flags=0);
+
+/**
+ * Sends a vote menu to all clients. See VoteMenu() for more information.
+ *
+ * @param menu Menu Handle.
+ * @param time Maximum time to leave menu on the screen.
+ * @param flags Optional voting flags.
+ * @return True on success, false if this menu already has a vote session
+ * in progress.
+ * @error Invalid Handle.
+ */
+stock bool:VoteMenuToAll(Handle:menu, time, flags=0)
+{
+ new total;
+ decl players[MaxClients];
+
+ for (new i=1; i<=MaxClients; i++)
+ {
+ if (!IsClientInGame(i) || IsFakeClient(i))
+ {
+ continue;
+ }
+ players[total++] = i;
+ }
+
+ return VoteMenu(menu, players, total, time, flags);
+}
+/**
+ * Callback for when a vote has ended and results are available.
+ *
+ * @param menu The menu being voted on.
+ * @param num_votes Number of votes tallied in total.
+ * @param num_clients Number of clients who could vote.
+ * @param client_info Array of clients. Use VOTEINFO_CLIENT_ defines.
+ * @param num_items Number of unique items that were selected.
+ * @param item_info Array of items, sorted by count. Use VOTEINFO_ITEM
+ * defines.
+ * @noreturn
+ */
+functag public VoteHandler(Handle:menu,
+ num_votes,
+ num_clients,
+ const client_info[][2],
+ num_items,
+ const item_info[][2]);
+
+/**
+ * Sets an advanced vote handling callback. If this callback is set,
+ * MenuAction_VoteEnd will not be called.
+ *
+ * @param menu Menu Handle.
+ * @param callback Callback function.
+ * @noreturn
+ * @error Invalid Handle or callback.
+ */
+native SetVoteResultCallback(Handle:menu, VoteHandler:callback);
+
+/**
+ * Returns the number of seconds you should "wait" before displaying
+ * a publicly invocable menu. This number is the time remaining until
+ * (last_vote + sm_vote_delay).
+ *
+ * @return Number of seconds to wait, or 0 for none.
+ */
+native CheckVoteDelay();
+
+/**
+ * Returns whether a client is in the pool of clients allowed
+ * to participate in the current vote. This is determined by
+ * the client list passed to VoteMenu().
+ *
+ * @param client Client index.
+ * @return True if client is allowed to vote, false otherwise.
+ * @error If no vote is in progress or client index is invalid.
+ */
+native bool:IsClientInVotePool(client);
+
+/**
+ * Redraws the current vote menu to a client in the voting pool.
+ *
+ * @param client Client index.
+ * @param revotes True to allow revotes, false otherwise.
+ * @return True on success, false if the client is in the vote pool
+ * but cannot vote again.
+ * @error No vote in progress, client is not in the voting pool,
+ * or client index is invalid.
+ */
+native bool:RedrawClientVoteMenu(client, bool:revotes=true);
+
+/**
+ * Returns a style's global Handle.
+ *
+ * @param style Menu Style.
+ * @return A Handle, or INVALID_HANDLE if not found or unusable.
+ */
+native Handle:GetMenuStyleHandle(MenuStyle:style);
+
+/**
+ * Creates a MenuPanel from a MenuStyle. Panels are used for drawing raw
+ * menus without any extra helper functions. The Handle must be closed
+ * with CloseHandle().
+ *
+ * @param hStyle MenuStyle Handle, or INVALID_HANDLE to use the default style.
+ * @return A new MenuPanel Handle.
+ * @error Invalid Handle other than INVALID_HANDLE.
+ */
+native Handle:CreatePanel(Handle:hStyle=INVALID_HANDLE);
+
+/**
+ * Creates a Menu from a MenuStyle. The Handle must be closed with
+ * CloseHandle().
+ *
+ * @param hStyle MenuStyle Handle, or INVALID_HANDLE to use the default style.
+ * @param handler Function which will receive menu actions.
+ * @param actions Optionally set which actions to receive. Select,
+ * Cancel, and End will always be received regardless
+ * of whether they are set or not. They are also
+ * the only default actions.
+ * @return A new menu Handle.
+ * @error Invalid Handle other than INVALID_HANDLE.
+ */
+native Handle:CreateMenuEx(Handle:hStyle=INVALID_HANDLE, MenuHandler:handler, MenuAction:actions=MENU_ACTIONS_DEFAULT);
+
+/**
+ * Returns whether a client is viewing a menu.
+ *
+ * @param client Client index.
+ * @param hStyle MenuStyle Handle, or INVALID_HANDLE to use the default style.
+ * @return A MenuSource value.
+ * @error Invalid Handle other than INVALID_HANDLE.
+ */
+native MenuSource:GetClientMenu(client, Handle:hStyle=INVALID_HANDLE);
+
+/**
+ * Cancels a menu on a client. This will only affect non-external menus.
+ *
+ * @param hStyle MenuStyle Handle, or INVALID_HANDLE to use the default style.
+ * @param client Client index.
+ * @param autoIgnore If true, no menus can be re-drawn on the client during
+ * the cancellation process.
+ * @return True if a menu was cancelled, false otherwise.
+ */
+native bool:CancelClientMenu(client, bool:autoIgnore=false, Handle:hStyle=INVALID_HANDLE);
+
+/**
+ * Returns a style's maximum items per page.
+ *
+ * @param hStyle MenuStyle Handle, or INVALID_HANDLE to use the default style.
+ * @return Maximum items per page.
+ * @error Invalid Handle other than INVALID_HANDLE.
+ */
+native GetMaxPageItems(Handle:hStyle=INVALID_HANDLE);
+
+/**
+ * Returns a MenuPanel's parent style.
+ *
+ * @param panel A MenuPanel Handle.
+ * @return The MenuStyle Handle that created the panel.
+ * @error Invalid Handle.
+ */
+native Handle:GetPanelStyle(Handle:panel);
+
+/**
+ * Sets the panel's title.
+ *
+ * @param panel A MenuPanel Handle.
+ * @param text Text to set as the title.
+ * @param onlyIfEmpty If true, the title will only be set if no title is set.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native Handle:SetPanelTitle(Handle:panel, const String:text[], bool:onlyIfEmpty=false);
+
+/**
+ * Draws an item on a panel. If the item takes up a slot, the position
+ * is returned.
+ *
+ * @param panel A MenuPanel Handle.
+ * @param text Display text to use. If not a raw line,
+ * the style may automatically add color markup.
+ * No numbering or newlines are needed.
+ * @param style ITEMDRAW style flags.
+ * @return A slot position, or 0 if item was a rawline or could not be drawn.
+ * @error Invalid Handle.
+ */
+native DrawPanelItem(Handle:panel, const String:text[], style=ITEMDRAW_DEFAULT);
+
+/**
+ * Draws a raw line of text on a panel, without any markup other than a newline.
+ *
+ * @param panel A MenuPanel Handle, or INVALID_HANDLE if inside a
+ * MenuAction_DisplayItem callback.
+ * @param text Display text to use.
+ * @return True on success, false if raw lines are not supported.
+ * @error Invalid Handle.
+ */
+native DrawPanelText(Handle:panel, const String:text[]);
+
+/**
+ * Returns whether or not the given drawing flags are supported by
+ * the menu style.
+ *
+ * @param panel A MenuPanel Handle.
+ * @param style ITEMDRAW style flags.
+ * @return True if item is drawable, false otherwise.
+ * @error Invalid Handle.
+ */
+native CanPanelDrawFlags(Handle:panel, style);
+
+/**
+ * Sets the selectable key map of a panel. This is not supported by
+ * all styles (only by Radio, as of this writing).
+ *
+ * @param panel A MenuPanel Handle.
+ * @param keys An integer where each bit N allows key
+ * N+1 to be selected. If no keys are selectable,
+ * then key 0 (bit 9) is automatically set.
+ * @return True if supported, false otherwise.
+ */
+native bool:SetPanelKeys(Handle:panel, keys);
+
+/**
+ * Sends a panel to a client. Unlike full menus, the handler
+ * function will only receive the following actions, both of
+ * which will have INVALID_HANDLE for a menu, and the client
+ * as param1.
+ *
+ * MenuAction_Select (param2 will be the key pressed)
+ * MenuAction_Cancel (param2 will be the reason)
+ *
+ * Also, if the menu fails to display, no callbacks will be called.
+ *
+ * @param panel A MenuPanel Handle.
+ * @param client A client to draw to.
+ * @param handler The MenuHandler function to catch actions with.
+ * @param time Time to hold the menu for.
+ * @return True on success, false on failure.
+ * @error Invalid Handle.
+ */
+native bool:SendPanelToClient(Handle:panel, client, MenuHandler:handler, time);
+
+/**
+ * @brief Returns the amount of text the menu can still hold. If this is
+ * limit is reached or overflowed, the text is silently truncated.
+ *
+ * Radio menus: Currently 511 characters (512 bytes).
+ * Valve menus: Currently -1 (no meaning).
+ *
+ * @param panel A MenuPanel Handle.
+ * @return Number of characters that the menu can still hold,
+ * or -1 if there is no known limit.
+ * @error Invalid Handle.
+ */
+native GetPanelTextRemaining(Handle:panel);
+
+/**
+ * @brief Returns the current key position.
+ *
+ * @param panel A MenuPanel Handle.
+ * @return Current key position starting at 1.
+ * @error Invalid Handle.
+ */
+native GetPanelCurrentKey(Handle:panel);
+
+/**
+ * @brief Sets the next key position. This cannot be used
+ * to traverse backwards.
+ *
+ * @param panel A MenuPanel Handle.
+ * @param key Key that is greater or equal to
+ * GetPanelCurrentKey().
+ * @return True on success, false otherwise.
+ * @error Invalid Handle.
+ */
+native bool:SetPanelCurrentKey(Handle:panel, key);
+
+/**
+ * @brief Redraws menu text from inside a MenuAction_DisplayItem callback.
+ *
+ * @param text Menu text to draw.
+ * @return Item position; must be returned via the callback.
+ */
+native RedrawMenuItem(const String:text[]);
+
+/**
+ * This function is provided for legacy code only. Some older plugins may use
+ * network messages instead of the panel API. This function wraps the panel
+ * API for eased portability into the SourceMod menu system.
+ *
+ * This function is only usable with the Radio Menu style. You do not need to
+ * split up your menu into multiple packets; SourceMod will break the string
+ * up internally.
+ *
+ * @param client Client index.
+ * @param str Full menu string as would be passed over the network.
+ * @param time Time to hold the menu for.
+ * @param keys Selectable key bitstring.
+ * @param handler Optional handler function, with the same rules as
+ * SendPanelToClient().
+ * @return True on success, false on failure.
+ * @error Invalid client index, or radio menus not supported.
+ */
+native bool:InternalShowMenu(client, const String:str[], time, keys=-1, MenuHandler:handler=MenuHandler:-1);
+
+/**
+ * Retrieves voting information from MenuAction_VoteEnd.
+ *
+ * @param param2 Second parameter of MenuAction_VoteEnd.
+ * @param winningVotes Number of votes received by the winning option.
+ * @param totalVotes Number of total votes received.
+ * @noreturn
+ */
+stock GetMenuVoteInfo(param2, &winningVotes, &totalVotes)
+{
+ winningVotes = param2 & 0xFFFF;
+ totalVotes = param2 >> 16;
+}
+
+/**
+ * Quick stock to determine whether voting is allowed. This doesn't let you
+ * fine-tune a reason for not voting, so it's not recommended for lazily
+ * telling clients that voting isn't allowed.
+ *
+ * @return True if voting is allowed, false if voting is in progress
+ * or the cooldown is active.
+ */
+stock bool:IsNewVoteAllowed()
+{
+ if (IsVoteInProgress() || CheckVoteDelay() != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
diff --git a/sourcemod-1.5-dev/scripting/include/morecolors.inc b/sourcemod-1.5-dev/scripting/include/morecolors.inc
new file mode 100644
index 0000000..3a416d8
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/morecolors.inc
@@ -0,0 +1,674 @@
+// MOAR COLORS
+// By Dr. McKay
+// Inspired by: https://forums.alliedmods.net/showthread.php?t=96831
+
+#if defined _colors_included
+ #endinput
+#endif
+#define _colors_included
+
+#include <regex>
+
+#define MORE_COLORS_VERSION "1.9.1"
+#define MAX_MESSAGE_LENGTH 256
+#define MAX_BUFFER_LENGTH (MAX_MESSAGE_LENGTH * 4)
+
+#define COLOR_RED 0xFF4040
+#define COLOR_BLUE 0x99CCFF
+#define COLOR_GRAY 0xCCCCCC
+#define COLOR_GREEN 0x3EFF3E
+
+#define GAME_DODS 0
+
+new bool:CSkipList[MAXPLAYERS + 1];
+new Handle:CTrie;
+new CTeamColors[][] = {{0xCCCCCC, 0x4D7942, 0xFF4040}}; // Multi-dimensional array for games that don't support SayText2. First index is the game index (as defined by the GAME_ defines), second index is team. 0 = spectator, 1 = team1, 2 = team2
+
+/**
+ * Prints a message to a specific client in the chat area.
+ * Supports color tags.
+ *
+ * @param client Client index.
+ * @param message Message (formatting rules).
+ * @noreturn
+ *
+ * On error/Errors: If the client is not connected an error will be thrown.
+ */
+stock CPrintToChat(client, const String:message[], any:...) {
+ CCheckTrie();
+ if(client <= 0 || client > MaxClients) {
+ ThrowError("Invalid client index %i", client);
+ }
+ if(!IsClientInGame(client)) {
+ ThrowError("Client %i is not in game", client);
+ }
+ decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH];
+ SetGlobalTransTarget(client);
+ Format(buffer, sizeof(buffer), "\x01%s", message);
+ VFormat(buffer2, sizeof(buffer2), buffer, 3);
+ CReplaceColorCodes(buffer2);
+ CSendMessage(client, buffer2);
+}
+
+/**
+ * Prints a message to all clients in the chat area.
+ * Supports color tags.
+ *
+ * @param client Client index.
+ * @param message Message (formatting rules).
+ * @noreturn
+ */
+stock CPrintToChatAll(const String:message[], any:...) {
+ CCheckTrie();
+ decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH];
+ for(new i = 1; i <= MaxClients; i++) {
+ if(!IsClientInGame(i) || CSkipList[i]) {
+ CSkipList[i] = false;
+ continue;
+ }
+ SetGlobalTransTarget(i);
+ Format(buffer, sizeof(buffer), "\x01%s", message);
+ VFormat(buffer2, sizeof(buffer2), buffer, 2);
+ CReplaceColorCodes(buffer2);
+ CSendMessage(i, buffer2);
+ }
+}
+
+/**
+ * Prints a message to a specific client in the chat area.
+ * Supports color tags and teamcolor tag.
+ *
+ * @param client Client index.
+ * @param author Author index whose color will be used for teamcolor tag.
+ * @param message Message (formatting rules).
+ * @noreturn
+ *
+ * On error/Errors: If the client or author are not connected an error will be thrown
+ */
+stock CPrintToChatEx(client, author, const String:message[], any:...) {
+ CCheckTrie();
+ if(client <= 0 || client > MaxClients) {
+ ThrowError("Invalid client index %i", client);
+ }
+ if(!IsClientInGame(client)) {
+ ThrowError("Client %i is not in game", client);
+ }
+ if(author <= 0 || author > MaxClients) {
+ ThrowError("Invalid client index %i", author);
+ }
+ if(!IsClientInGame(author)) {
+ ThrowError("Client %i is not in game", author);
+ }
+ decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH];
+ SetGlobalTransTarget(client);
+ Format(buffer, sizeof(buffer), "\x01%s", message);
+ VFormat(buffer2, sizeof(buffer2), buffer, 4);
+ CReplaceColorCodes(buffer2, author);
+ CSendMessage(client, buffer2, author);
+}
+
+/**
+ * Prints a message to all clients in the chat area.
+ * Supports color tags and teamcolor tag.
+ *
+ * @param author Author index whose color will be used for teamcolor tag.
+ * @param message Message (formatting rules).
+ * @noreturn
+ *
+ * On error/Errors: If the author is not connected an error will be thrown.
+ */
+stock CPrintToChatAllEx(author, const String:message[], any:...) {
+ CCheckTrie();
+ if(author <= 0 || author > MaxClients) {
+ ThrowError("Invalid client index %i", author);
+ }
+ if(!IsClientInGame(author)) {
+ ThrowError("Client %i is not in game", author);
+ }
+ decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH];
+ for(new i = 1; i <= MaxClients; i++) {
+ if(!IsClientInGame(i) || CSkipList[i]) {
+ CSkipList[i] = false;
+ continue;
+ }
+ SetGlobalTransTarget(i);
+ Format(buffer, sizeof(buffer), "\x01%s", message);
+ VFormat(buffer2, sizeof(buffer2), buffer, 3);
+ CReplaceColorCodes(buffer2, author);
+ CSendMessage(i, buffer2, author);
+ }
+}
+
+/**
+ * Sends a SayText2 usermessage
+ *
+ * @param client Client to send usermessage to
+ * @param message Message to send
+ * @noreturn
+ */
+stock CSendMessage(client, const String:message[], author=0) {
+ if(author == 0) {
+ author = client;
+ }
+ decl String:buffer[MAX_MESSAGE_LENGTH], String:game[16];
+ GetGameFolderName(game, sizeof(game));
+ strcopy(buffer, sizeof(buffer), message);
+ new UserMsg:index = GetUserMessageId("SayText2");
+ if(index == INVALID_MESSAGE_ID) {
+ if(StrEqual(game, "dod")) {
+ new team = GetClientTeam(author);
+ if(team == 0) {
+ ReplaceString(buffer, sizeof(buffer), "\x03", "\x04", false); // Unassigned gets green
+ } else {
+ decl String:temp[16];
+ Format(temp, sizeof(temp), "\x07%06X", CTeamColors[GAME_DODS][team - 1]);
+ ReplaceString(buffer, sizeof(buffer), "\x03", temp, false);
+ }
+ }
+ PrintToChat(client, "%s", buffer);
+ return;
+ }
+ new Handle:buf = StartMessageOne("SayText2", client, USERMSG_RELIABLE|USERMSG_BLOCKHOOKS);
+ if(GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && GetUserMessageType() == UM_Protobuf) {
+ PbSetInt(buf, "ent_idx", author);
+ PbSetBool(buf, "chat", true);
+ PbSetString(buf, "msg_name", buffer);
+ PbAddString(buf, "params", "");
+ PbAddString(buf, "params", "");
+ PbAddString(buf, "params", "");
+ PbAddString(buf, "params", "");
+ } else {
+ BfWriteByte(buf, author); // Message author
+ BfWriteByte(buf, true); // Chat message
+ BfWriteString(buf, buffer); // Message text
+ }
+ EndMessage();
+}
+
+/**
+ * This function should only be used right in front of
+ * CPrintToChatAll or CPrintToChatAllEx. It causes those functions
+ * to skip the specified client when printing the message.
+ * After printing the message, the client will no longer be skipped.
+ *
+ * @param client Client index
+ * @noreturn
+ */
+stock CSkipNextClient(client) {
+ if(client <= 0 || client > MaxClients) {
+ ThrowError("Invalid client index %i", client);
+ }
+ CSkipList[client] = true;
+}
+
+/**
+ * Checks if the colors trie is initialized and initializes it if it's not (used internally)
+ *
+ * @return No return
+ */
+stock CCheckTrie() {
+ if(CTrie == INVALID_HANDLE) {
+ CTrie = InitColorTrie();
+ }
+}
+
+/**
+ * Replaces color tags in a string with color codes (used internally by CPrintToChat, CPrintToChatAll, CPrintToChatEx, and CPrintToChatAllEx
+ *
+ * @param buffer String.
+ * @param author Optional client index to use for {teamcolor} tags, or 0 for none
+ * @param removeTags Optional boolean value to determine whether we're replacing tags with colors, or just removing tags, used by CRemoveTags
+ * @param maxlen Optional value for max buffer length, used by CRemoveTags
+ * @noreturn
+ *
+ * On error/Errors: If the client index passed for author is invalid or not in game.
+ */
+stock CReplaceColorCodes(String:buffer[], author=0, bool:removeTags=false, maxlen=MAX_BUFFER_LENGTH) {
+ CCheckTrie();
+ if(!removeTags) {
+ ReplaceString(buffer, maxlen, "{default}", "\x01", false);
+ } else {
+ ReplaceString(buffer, maxlen, "{default}", "", false);
+ ReplaceString(buffer, maxlen, "{teamcolor}", "", false);
+ }
+ if(author != 0 && !removeTags) {
+ if(author < 0 || author > MaxClients) {
+ ThrowError("Invalid client index %i", author);
+ }
+ if(!IsClientInGame(author)) {
+ ThrowError("Client %i is not in game", author);
+ }
+ ReplaceString(buffer, maxlen, "{teamcolor}", "\x03", false);
+ }
+ new cursor = 0;
+ new value;
+ decl String:tag[32], String:buff[32], String:output[maxlen];
+ strcopy(output, maxlen, buffer);
+ // Since the string's size is going to be changing, output will hold the replaced string and we'll search buffer
+
+ new Handle:regex = CompileRegex("{[a-zA-Z0-9]+}");
+ for(new i = 0; i < 1000; i++) { // The RegEx extension is quite flaky, so we have to loop here :/. This loop is supposed to be infinite and broken by return, but conditions have been added to be safe.
+ if(MatchRegex(regex, buffer[cursor]) < 1) {
+ CloseHandle(regex);
+ strcopy(buffer, maxlen, output);
+ return;
+ }
+ GetRegexSubString(regex, 0, tag, sizeof(tag));
+ CStrToLower(tag);
+ cursor = StrContains(buffer[cursor], tag, false) + cursor + 1;
+ strcopy(buff, sizeof(buff), tag);
+ ReplaceString(buff, sizeof(buff), "{", "");
+ ReplaceString(buff, sizeof(buff), "}", "");
+
+ if(!GetTrieValue(CTrie, buff, value)) {
+ continue;
+ }
+
+ if(removeTags) {
+ ReplaceString(output, maxlen, tag, "", false);
+ } else {
+ Format(buff, sizeof(buff), "\x07%06X", value);
+ ReplaceString(output, maxlen, tag, buff, false);
+ }
+ }
+ LogError("[MORE COLORS] Infinite loop broken.");
+}
+
+/**
+ * Gets a part of a string
+ *
+ * @param input String to get the part from
+ * @param output Buffer to write to
+ * @param maxlen Max length of output buffer
+ * @param start Position to start at
+ * @param numChars Number of characters to return, or 0 for the end of the string
+ * @noreturn
+ */
+stock CSubString(const String:input[], String:output[], maxlen, start, numChars=0) {
+ new i = 0;
+ for(;;) {
+ if(i == maxlen - 1 || i >= numChars || input[start + i] == '\0') {
+ output[i] = '\0';
+ return;
+ }
+ output[i] = input[start + i];
+ i++;
+ }
+}
+
+/**
+ * Converts a string to lowercase
+ *
+ * @param buffer String to convert
+ * @noreturn
+ */
+stock CStrToLower(String:buffer[]) {
+ new len = strlen(buffer);
+ for(new i = 0; i < len; i++) {
+ buffer[i] = CharToLower(buffer[i]);
+ }
+}
+
+/**
+ * Adds a color to the colors trie
+ *
+ * @param name Color name, without braces
+ * @param color Hexadecimal representation of the color (0xRRGGBB)
+ * @return True if color was added successfully, false if a color already exists with that name
+ */
+stock bool:CAddColor(const String:name[], color) {
+ CCheckTrie();
+ new value;
+ if(GetTrieValue(CTrie, name, value)) {
+ return false;
+ }
+ decl String:newName[64];
+ strcopy(newName, sizeof(newName), name);
+ CStrToLower(newName);
+ SetTrieValue(CTrie, newName, color);
+ return true;
+}
+
+/**
+ * Removes color tags from a message
+ *
+ * @param message Message to remove tags from
+ * @param maxlen Maximum buffer length
+ * @noreturn
+ */
+stock CRemoveTags(String:message[], maxlen) {
+ CReplaceColorCodes(message, 0, true, maxlen);
+}
+
+/**
+ * Replies to a command with colors
+ *
+ * @param client Client to reply to
+ * @param message Message (formatting rules)
+ * @noreturn
+ */
+stock CReplyToCommand(client, const String:message[], any:...) {
+ decl String:buffer[MAX_BUFFER_LENGTH];
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), message, 3);
+ if(GetCmdReplySource() == SM_REPLY_TO_CONSOLE) {
+ CRemoveTags(buffer, sizeof(buffer));
+ PrintToConsole(client, "%s", buffer);
+ } else {
+ CPrintToChat(client, "%s", buffer);
+ }
+}
+
+/**
+ * Replies to a command with colors
+ *
+ * @param client Client to reply to
+ * @param author Client to use for {teamcolor}
+ * @param message Message (formatting rules)
+ * @noreturn
+ */
+stock CReplyToCommandEx(client, author, const String:message[], any:...) {
+ decl String:buffer[MAX_BUFFER_LENGTH];
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), message, 4);
+ if(GetCmdReplySource() == SM_REPLY_TO_CONSOLE) {
+ CRemoveTags(buffer, sizeof(buffer));
+ PrintToConsole(client, "%s", buffer);
+ } else {
+ CPrintToChatEx(client, author, "%s", buffer);
+ }
+}
+
+/**
+ * Shows admin activity with colors
+ *
+ * @param client Client performing an action
+ * @param message Message (formatting rules)
+ * @noreturn
+ */
+stock CShowActivity(client, const String:message[], any:...) {
+ CCheckTrie();
+ if(client < 0 || client > MaxClients) {
+ ThrowError("Invalid client index %d", client);
+ }
+ if(client != 0 && !IsClientInGame(client)) {
+ ThrowError("Client %d is not in game", client);
+ }
+ decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH];
+ Format(buffer, sizeof(buffer), "\x01%s", message);
+ VFormat(buffer2, sizeof(buffer2), buffer, 3);
+ CReplaceColorCodes(buffer2);
+ ShowActivity(client, "%s", buffer2);
+}
+
+/**
+ * Shows admin activity with colors
+ *
+ * @param client Client performing an action
+ * @param tag Tag to prepend to the message (color tags supported)
+ * @param message Message (formatting rules)
+ * @noreturn
+ */
+stock CShowActivityEx(client, const String:tag[], const String:message[], any:...) {
+ CCheckTrie();
+ if(client < 0 || client > MaxClients) {
+ ThrowError("Invalid client index %d", client);
+ }
+ if(client != 0 && !IsClientInGame(client)) {
+ ThrowError("Client %d is not in game", client);
+ }
+ decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH];
+ Format(buffer, sizeof(buffer), "\x01%s", message);
+ VFormat(buffer2, sizeof(buffer2), buffer, 4);
+ CReplaceColorCodes(buffer2);
+ strcopy(buffer, sizeof(buffer), tag);
+ CReplaceColorCodes(buffer);
+ ShowActivityEx(client, tag, "%s", buffer2);
+}
+
+/**
+ * Shows admin activity with colors
+ *
+ * @param client Client performing an action
+ * @param tag Tag to prepend to the message (color tags supported)
+ * @param message Message (formatting rules)
+ * @noreturn
+ */
+stock CShowActivity2(client, const String:tag[], const String:message[], any:...) {
+ CCheckTrie();
+ if(client < 0 || client > MaxClients) {
+ ThrowError("Invalid client index %d", client);
+ }
+ if(client != 0 && !IsClientInGame(client)) {
+ ThrowError("Client %d is not in game", client);
+ }
+ decl String:buffer[MAX_BUFFER_LENGTH], String:buffer2[MAX_BUFFER_LENGTH];
+ Format(buffer, sizeof(buffer), "\x01%s", message);
+ VFormat(buffer2, sizeof(buffer2), buffer, 4);
+ CReplaceColorCodes(buffer2);
+ strcopy(buffer, sizeof(buffer), tag);
+ CReplaceColorCodes(buffer);
+ ShowActivity2(client, buffer, "%s", buffer2);
+}
+
+/**
+ * Determines whether a color name exists
+ *
+ * @param color The color name to check
+ * @return True if the color exists, false otherwise
+ */
+stock bool:CColorExists(const String:color[]) {
+ CCheckTrie();
+ new temp;
+ return GetTrieValue(CTrie, color, temp);
+}
+
+/**
+ * Returns the hexadecimal representation of a client's team color (will NOT initialize the trie)
+ *
+ * @param client Client to get the team color for
+ * @return Client's team color in hexadecimal, or green if unknown
+ * On error/Errors: If the client index passed is invalid or not in game.
+ */
+stock CGetTeamColor(client) {
+ if(client <= 0 || client > MaxClients) {
+ ThrowError("Invalid client index %i", client);
+ }
+ if(!IsClientInGame(client)) {
+ ThrowError("Client %i is not in game", client);
+ }
+ new value;
+ switch(GetClientTeam(client)) {
+ case 1: {
+ value = COLOR_GRAY;
+ }
+ case 2: {
+ value = COLOR_RED;
+ }
+ case 3: {
+ value = COLOR_BLUE;
+ }
+ default: {
+ value = COLOR_GREEN;
+ }
+ }
+ return value;
+}
+
+stock Handle:InitColorTrie() {
+ new Handle:hTrie = CreateTrie();
+ SetTrieValue(hTrie, "aliceblue", 0xF0F8FF);
+ SetTrieValue(hTrie, "allies", 0x4D7942); // same as Allies team in DoD:S
+ SetTrieValue(hTrie, "ancient", 0xEB4B4B); // same as Ancient item rarity in Dota 2
+ SetTrieValue(hTrie, "antiquewhite", 0xFAEBD7);
+ SetTrieValue(hTrie, "aqua", 0x00FFFF);
+ SetTrieValue(hTrie, "aquamarine", 0x7FFFD4);
+ SetTrieValue(hTrie, "arcana", 0xADE55C); // same as Arcana item rarity in Dota 2
+ SetTrieValue(hTrie, "axis", 0xFF4040); // same as Axis team in DoD:S
+ SetTrieValue(hTrie, "azure", 0x007FFF);
+ SetTrieValue(hTrie, "beige", 0xF5F5DC);
+ SetTrieValue(hTrie, "bisque", 0xFFE4C4);
+ SetTrieValue(hTrie, "black", 0x000000);
+ SetTrieValue(hTrie, "blanchedalmond", 0xFFEBCD);
+ SetTrieValue(hTrie, "blue", 0x99CCFF); // same as BLU/Counter-Terrorist team color
+ SetTrieValue(hTrie, "blueviolet", 0x8A2BE2);
+ SetTrieValue(hTrie, "brown", 0xA52A2A);
+ SetTrieValue(hTrie, "burlywood", 0xDEB887);
+ SetTrieValue(hTrie, "cadetblue", 0x5F9EA0);
+ SetTrieValue(hTrie, "chartreuse", 0x7FFF00);
+ SetTrieValue(hTrie, "chocolate", 0xD2691E);
+ SetTrieValue(hTrie, "collectors", 0xAA0000); // same as Collector's item quality in TF2
+ SetTrieValue(hTrie, "common", 0xB0C3D9); // same as Common item rarity in Dota 2
+ SetTrieValue(hTrie, "community", 0x70B04A); // same as Community item quality in TF2
+ SetTrieValue(hTrie, "coral", 0xFF7F50);
+ SetTrieValue(hTrie, "cornflowerblue", 0x6495ED);
+ SetTrieValue(hTrie, "cornsilk", 0xFFF8DC);
+ SetTrieValue(hTrie, "corrupted", 0xA32C2E); // same as Corrupted item quality in Dota 2
+ SetTrieValue(hTrie, "crimson", 0xDC143C);
+ SetTrieValue(hTrie, "cyan", 0x00FFFF);
+ SetTrieValue(hTrie, "darkblue", 0x00008B);
+ SetTrieValue(hTrie, "darkcyan", 0x008B8B);
+ SetTrieValue(hTrie, "darkgoldenrod", 0xB8860B);
+ SetTrieValue(hTrie, "darkgray", 0xA9A9A9);
+ SetTrieValue(hTrie, "darkgrey", 0xA9A9A9);
+ SetTrieValue(hTrie, "darkgreen", 0x006400);
+ SetTrieValue(hTrie, "darkkhaki", 0xBDB76B);
+ SetTrieValue(hTrie, "darkmagenta", 0x8B008B);
+ SetTrieValue(hTrie, "darkolivegreen", 0x556B2F);
+ SetTrieValue(hTrie, "darkorange", 0xFF8C00);
+ SetTrieValue(hTrie, "darkorchid", 0x9932CC);
+ SetTrieValue(hTrie, "darkred", 0x8B0000);
+ SetTrieValue(hTrie, "darksalmon", 0xE9967A);
+ SetTrieValue(hTrie, "darkseagreen", 0x8FBC8F);
+ SetTrieValue(hTrie, "darkslateblue", 0x483D8B);
+ SetTrieValue(hTrie, "darkslategray", 0x2F4F4F);
+ SetTrieValue(hTrie, "darkslategrey", 0x2F4F4F);
+ SetTrieValue(hTrie, "darkturquoise", 0x00CED1);
+ SetTrieValue(hTrie, "darkviolet", 0x9400D3);
+ SetTrieValue(hTrie, "deeppink", 0xFF1493);
+ SetTrieValue(hTrie, "deepskyblue", 0x00BFFF);
+ SetTrieValue(hTrie, "dimgray", 0x696969);
+ SetTrieValue(hTrie, "dimgrey", 0x696969);
+ SetTrieValue(hTrie, "dodgerblue", 0x1E90FF);
+ SetTrieValue(hTrie, "exalted", 0xCCCCCD); // same as Exalted item quality in Dota 2
+ SetTrieValue(hTrie, "firebrick", 0xB22222);
+ SetTrieValue(hTrie, "floralwhite", 0xFFFAF0);
+ SetTrieValue(hTrie, "forestgreen", 0x228B22);
+ SetTrieValue(hTrie, "frozen", 0x4983B3); // same as Frozen item quality in Dota 2
+ SetTrieValue(hTrie, "fuchsia", 0xFF00FF);
+ SetTrieValue(hTrie, "fullblue", 0x0000FF);
+ SetTrieValue(hTrie, "fullred", 0xFF0000);
+ SetTrieValue(hTrie, "gainsboro", 0xDCDCDC);
+ SetTrieValue(hTrie, "genuine", 0x4D7455); // same as Genuine item quality in TF2
+ SetTrieValue(hTrie, "ghostwhite", 0xF8F8FF);
+ SetTrieValue(hTrie, "gold", 0xFFD700);
+ SetTrieValue(hTrie, "goldenrod", 0xDAA520);
+ SetTrieValue(hTrie, "gray", 0xCCCCCC); // same as spectator team color
+ SetTrieValue(hTrie, "grey", 0xCCCCCC);
+ SetTrieValue(hTrie, "green", 0x3EFF3E);
+ SetTrieValue(hTrie, "greenyellow", 0xADFF2F);
+ SetTrieValue(hTrie, "haunted", 0x38F3AB); // same as Haunted item quality in TF2
+ SetTrieValue(hTrie, "honeydew", 0xF0FFF0);
+ SetTrieValue(hTrie, "hotpink", 0xFF69B4);
+ SetTrieValue(hTrie, "immortal", 0xE4AE33); // same as Immortal item rarity in Dota 2
+ SetTrieValue(hTrie, "indianred", 0xCD5C5C);
+ SetTrieValue(hTrie, "indigo", 0x4B0082);
+ SetTrieValue(hTrie, "ivory", 0xFFFFF0);
+ SetTrieValue(hTrie, "khaki", 0xF0E68C);
+ SetTrieValue(hTrie, "lavender", 0xE6E6FA);
+ SetTrieValue(hTrie, "lavenderblush", 0xFFF0F5);
+ SetTrieValue(hTrie, "lawngreen", 0x7CFC00);
+ SetTrieValue(hTrie, "legendary", 0xD32CE6); // same as Legendary item rarity in Dota 2
+ SetTrieValue(hTrie, "lemonchiffon", 0xFFFACD);
+ SetTrieValue(hTrie, "lightblue", 0xADD8E6);
+ SetTrieValue(hTrie, "lightcoral", 0xF08080);
+ SetTrieValue(hTrie, "lightcyan", 0xE0FFFF);
+ SetTrieValue(hTrie, "lightgoldenrodyellow", 0xFAFAD2);
+ SetTrieValue(hTrie, "lightgray", 0xD3D3D3);
+ SetTrieValue(hTrie, "lightgrey", 0xD3D3D3);
+ SetTrieValue(hTrie, "lightgreen", 0x99FF99);
+ SetTrieValue(hTrie, "lightpink", 0xFFB6C1);
+ SetTrieValue(hTrie, "lightsalmon", 0xFFA07A);
+ SetTrieValue(hTrie, "lightseagreen", 0x20B2AA);
+ SetTrieValue(hTrie, "lightskyblue", 0x87CEFA);
+ SetTrieValue(hTrie, "lightslategray", 0x778899);
+ SetTrieValue(hTrie, "lightslategrey", 0x778899);
+ SetTrieValue(hTrie, "lightsteelblue", 0xB0C4DE);
+ SetTrieValue(hTrie, "lightyellow", 0xFFFFE0);
+ SetTrieValue(hTrie, "lime", 0x00FF00);
+ SetTrieValue(hTrie, "limegreen", 0x32CD32);
+ SetTrieValue(hTrie, "linen", 0xFAF0E6);
+ SetTrieValue(hTrie, "magenta", 0xFF00FF);
+ SetTrieValue(hTrie, "maroon", 0x800000);
+ SetTrieValue(hTrie, "mediumaquamarine", 0x66CDAA);
+ SetTrieValue(hTrie, "mediumblue", 0x0000CD);
+ SetTrieValue(hTrie, "mediumorchid", 0xBA55D3);
+ SetTrieValue(hTrie, "mediumpurple", 0x9370D8);
+ SetTrieValue(hTrie, "mediumseagreen", 0x3CB371);
+ SetTrieValue(hTrie, "mediumslateblue", 0x7B68EE);
+ SetTrieValue(hTrie, "mediumspringgreen", 0x00FA9A);
+ SetTrieValue(hTrie, "mediumturquoise", 0x48D1CC);
+ SetTrieValue(hTrie, "mediumvioletred", 0xC71585);
+ SetTrieValue(hTrie, "midnightblue", 0x191970);
+ SetTrieValue(hTrie, "mintcream", 0xF5FFFA);
+ SetTrieValue(hTrie, "mistyrose", 0xFFE4E1);
+ SetTrieValue(hTrie, "moccasin", 0xFFE4B5);
+ SetTrieValue(hTrie, "mythical", 0x8847FF); // same as Mythical item rarity in Dota 2
+ SetTrieValue(hTrie, "navajowhite", 0xFFDEAD);
+ SetTrieValue(hTrie, "navy", 0x000080);
+ SetTrieValue(hTrie, "normal", 0xB2B2B2); // same as Normal item quality in TF2
+ SetTrieValue(hTrie, "oldlace", 0xFDF5E6);
+ SetTrieValue(hTrie, "olive", 0x9EC34F);
+ SetTrieValue(hTrie, "olivedrab", 0x6B8E23);
+ SetTrieValue(hTrie, "orange", 0xFFA500);
+ SetTrieValue(hTrie, "orangered", 0xFF4500);
+ SetTrieValue(hTrie, "orchid", 0xDA70D6);
+ SetTrieValue(hTrie, "palegoldenrod", 0xEEE8AA);
+ SetTrieValue(hTrie, "palegreen", 0x98FB98);
+ SetTrieValue(hTrie, "paleturquoise", 0xAFEEEE);
+ SetTrieValue(hTrie, "palevioletred", 0xD87093);
+ SetTrieValue(hTrie, "papayawhip", 0xFFEFD5);
+ SetTrieValue(hTrie, "peachpuff", 0xFFDAB9);
+ SetTrieValue(hTrie, "peru", 0xCD853F);
+ SetTrieValue(hTrie, "pink", 0xFFC0CB);
+ SetTrieValue(hTrie, "plum", 0xDDA0DD);
+ SetTrieValue(hTrie, "powderblue", 0xB0E0E6);
+ SetTrieValue(hTrie, "purple", 0x800080);
+ SetTrieValue(hTrie, "rare", 0x4B69FF); // same as Rare item rarity in Dota 2
+ SetTrieValue(hTrie, "red", 0xFF4040); // same as RED/Terrorist team color
+ SetTrieValue(hTrie, "rosybrown", 0xBC8F8F);
+ SetTrieValue(hTrie, "royalblue", 0x4169E1);
+ SetTrieValue(hTrie, "saddlebrown", 0x8B4513);
+ SetTrieValue(hTrie, "salmon", 0xFA8072);
+ SetTrieValue(hTrie, "sandybrown", 0xF4A460);
+ SetTrieValue(hTrie, "seagreen", 0x2E8B57);
+ SetTrieValue(hTrie, "seashell", 0xFFF5EE);
+ SetTrieValue(hTrie, "selfmade", 0x70B04A); // same as Self-Made item quality in TF2
+ SetTrieValue(hTrie, "sienna", 0xA0522D);
+ SetTrieValue(hTrie, "silver", 0xC0C0C0);
+ SetTrieValue(hTrie, "skyblue", 0x87CEEB);
+ SetTrieValue(hTrie, "slateblue", 0x6A5ACD);
+ SetTrieValue(hTrie, "slategray", 0x708090);
+ SetTrieValue(hTrie, "slategrey", 0x708090);
+ SetTrieValue(hTrie, "snow", 0xFFFAFA);
+ SetTrieValue(hTrie, "springgreen", 0x00FF7F);
+ SetTrieValue(hTrie, "steelblue", 0x4682B4);
+ SetTrieValue(hTrie, "strange", 0xCF6A32); // same as Strange item quality in TF2
+ SetTrieValue(hTrie, "tan", 0xD2B48C);
+ SetTrieValue(hTrie, "teal", 0x008080);
+ SetTrieValue(hTrie, "thistle", 0xD8BFD8);
+ SetTrieValue(hTrie, "tomato", 0xFF6347);
+ SetTrieValue(hTrie, "turquoise", 0x40E0D0);
+ SetTrieValue(hTrie, "uncommon", 0xB0C3D9); // same as Uncommon item rarity in Dota 2
+ SetTrieValue(hTrie, "unique", 0xFFD700); // same as Unique item quality in TF2
+ SetTrieValue(hTrie, "unusual", 0x8650AC); // same as Unusual item quality in TF2
+ SetTrieValue(hTrie, "valve", 0xA50F79); // same as Valve item quality in TF2
+ SetTrieValue(hTrie, "vintage", 0x476291); // same as Vintage item quality in TF2
+ SetTrieValue(hTrie, "violet", 0xEE82EE);
+ SetTrieValue(hTrie, "wheat", 0xF5DEB3);
+ SetTrieValue(hTrie, "white", 0xFFFFFF);
+ SetTrieValue(hTrie, "whitesmoke", 0xF5F5F5);
+ SetTrieValue(hTrie, "yellow", 0xFFFF00);
+ SetTrieValue(hTrie, "yellowgreen", 0x9ACD32);
+ return hTrie;
+} \ No newline at end of file
diff --git a/sourcemod-1.5-dev/scripting/include/nextmap.inc b/sourcemod-1.5-dev/scripting/include/nextmap.inc
new file mode 100644
index 0000000..af539f7
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/nextmap.inc
@@ -0,0 +1,84 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _nextmap_included_
+ #endinput
+#endif
+#define _nextmap_included_
+
+/**
+ * Sets SourceMod's internal nextmap.
+ * Equivalent to changing sm_nextmap but with an added validity check.
+ *
+ * @param map Next map to set.
+ * @return True if the nextmap was set, false if map was invalid.
+ */
+native bool:SetNextMap(const String:map[]);
+
+/**
+ * Returns SourceMod's internal nextmap.
+ *
+ * @param map Buffer to store the nextmap name.
+ * @param maxlen Maximum length of the map buffer.
+ * @return True if a Map was found and copied, false if no nextmap is set (map will be unchanged).
+ */
+native bool:GetNextMap(String:map[], maxlen);
+
+/**
+ * Changes the current map and records the reason for the change with maphistory
+ *
+ * @param map Map to change to.
+ * @param reason Reason for change.
+ * @noreturn
+ */
+native ForceChangeLevel(const String:map[], const String:reason[]);
+
+/**
+ * Gets the current number of maps in the map history
+ *
+ * @return Number of maps.
+ */
+native GetMapHistorySize();
+
+/**
+ * Retrieves a map from the map history list.
+ *
+ * @param item Item number. Must be 0 or greater and less than GetMapHistorySize().
+ * @param map Buffer to store the map name.
+ * @param mapLen Length of map buffer.
+ * @param reason Buffer to store the change reason.
+ * @param reasonLen Length of the reason buffer.
+ * @param startTime Time the map started.
+ * @noreturn
+ * @error Invalid item number.
+ */
+native GetMapHistory(item, String:map[], mapLen, String:reason[], reasonLen, &startTime); \ No newline at end of file
diff --git a/sourcemod-1.5-dev/scripting/include/profiler.inc b/sourcemod-1.5-dev/scripting/include/profiler.inc
new file mode 100644
index 0000000..68f1ca7
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/profiler.inc
@@ -0,0 +1,77 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _profiler_included
+ #endinput
+#endif
+#define _profiler_included
+
+/**
+ * ONLY AVAILABLE ON WINDOWS RIGHT NOW K.
+ */
+
+/**
+ * Creates a new profile object. The Handle must be freed
+ * using CloseHandle().
+ *
+ * @return Handle to the profiler object.
+ */
+native Handle:CreateProfiler();
+
+/**
+ * Starts profiling.
+ *
+ * @param prof Profiling object.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native StartProfiling(Handle:prof);
+
+/**
+ * Stops profiling.
+ *
+ * @param prof Profiling object.
+ * @noreturn
+ * @error Invalid Handle or profiling was never started.
+ */
+native StopProfiling(Handle:prof);
+
+/**
+ * Returns the amount of high-precision time in seconds
+ * that passed during the profiler's last start/stop
+ * cycle.
+ *
+ * @param prof Profiling object.
+ * @return Time elapsed in seconds.
+ * @error Invalid Handle.
+ */
+native Float:GetProfilerTime(Handle:prof);
diff --git a/sourcemod-1.5-dev/scripting/include/protobuf.inc b/sourcemod-1.5-dev/scripting/include/protobuf.inc
new file mode 100644
index 0000000..56f0bd9
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/protobuf.inc
@@ -0,0 +1,368 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2013 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _protobuf_included
+#endinput
+#endif
+#define _protobuf_included
+
+#define PB_FIELD_NOT_REPEATED -1
+
+/**
+ * Reads an int32, uint32, sint32, fixed32, sfixed32, or enum value from a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param index Index into repeated field.
+ * @return Integer value read.
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbReadInt(Handle:pb, const String:field[], index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Reads a float or downcasted double from a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param index Index into repeated field.
+ * @return Float value read.
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native Float:PbReadFloat(Handle:pb, const String:field[], index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Reads a bool from a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param index Index into repeated field.
+ * @return Boolean value read.
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native bool:PbReadBool(Handle:pb, const String:field[], index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Reads a string from a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param buffer Destination string buffer.
+ * @param maxlength Maximum length of output string buffer.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbReadString(Handle:pb, const String:field[], String:buffer[], maxlength, index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Reads an RGBA color value from a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param buffer Destination color buffer.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbReadColor(Handle:pb, const String:field[], buffer[4], index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Reads an XYZ angle value from a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param buffer Destination angle buffer.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbReadAngle(Handle:pb, const String:field[], Float:buffer[3], index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Reads an XYZ vector value from a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param buffer Destination vector buffer.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbReadVector(Handle:pb, const String:field[], Float:buffer[3], index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Reads an XY vector value from a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param buffer Destination vector buffer.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbReadVector2D(Handle:pb, const String:field[], Float:buffer[2], index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Gets the number of elements in a repeated field of a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @return Number of elements in the field.
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbGetRepeatedFieldCount(Handle:pb, const String:field[]);
+
+/**
+ * Sets an int32, uint32, sint32, fixed32, sfixed32, or enum value on a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param value Integer value to set.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbSetInt(Handle:pb, const String:field[], value, index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Sets a float or double on a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param value Float value to set.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbSetFloat(Handle:pb, const String:field[], Float:value, index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Sets a bool on a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param value Boolean value to set.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbSetBool(Handle:pb, const String:field[], bool:value, index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Sets a string on a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param value String value to set.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbSetString(Handle:pb, const String:field[], const String:value[], index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Sets an RGBA color on a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param color Color value to set.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbSetColor(Handle:pb, const String:field[], const color[4], index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Sets an XYZ angle on a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param angle Angle value to set.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbSetAngle(Handle:pb, const String:field[], const Float:angle[3], index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Sets an XYZ vector on a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param vec Vector value to set.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbSetVector(Handle:pb, const String:field[], const Float:vec[3], index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Sets an XY vector on a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param vec Vector value to set.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbSetVector2D(Handle:pb, const String:field[], const Float:vec[2], index=PB_FIELD_NOT_REPEATED);
+
+/**
+ * Add an int32, uint32, sint32, fixed32, sfixed32, or enum value to a protobuf message repeated field.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param value Integer value to add.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbAddInt(Handle:pb, const String:field[], value);
+
+/**
+ * Add a float or double to a protobuf message repeated field.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param value Float value to add.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbAddFloat(Handle:pb, const String:field[], Float:value);
+
+/**
+ * Add a bool to a protobuf message repeated field.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param value Boolean value to add.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbAddBool(Handle:pb, const String:field[], bool:value);
+
+/**
+ * Add a string to a protobuf message repeated field.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param value String value to add.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbAddString(Handle:pb, const String:field[], const String:value[]);
+
+/**
+ * Add an RGBA color to a protobuf message repeated field.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param color Color value to add.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbAddColor(Handle:pb, const String:field[], const color[4]);
+
+/**
+ * Add an XYZ angle to a protobuf message repeated field.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param angle Angle value to add.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbAddAngle(Handle:pb, const String:field[], const Float:angle[3]);
+
+/**
+ * Add an XYZ vector to a protobuf message repeated field.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param vec Vector value to add.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbAddVector(Handle:pb, const String:field[], const Float:vec[3]);
+
+/**
+ * Add an XY vector to a protobuf message repeated field.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param vec Vector value to add.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbAddVector2D(Handle:pb, const String:field[], const Float:vec[2]);
+
+/**
+ * Removes a value by index from a protobuf message repeated field.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param index Index into repeated field.
+ * @noreturn
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native PbRemoveRepeatedFieldValue(Handle:pb, const String:field[], index);
+
+/**
+ * Retrieve a handle to an embedded protobuf message in a protobuf message.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @return protobuf handle to embedded message.
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native Handle:PbReadMessage(Handle:pb, const String:field[]);
+
+/**
+ * Retrieve a handle to an embedded protobuf message in a protobuf message repeated field.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @param index Index in the repeated field.
+ * @return protobuf handle to embedded message.
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native Handle:PbReadRepeatedMessage(Handle:pb, const String:field[], index);
+
+/**
+ * Adds an embedded protobuf message to a protobuf message repeated field.
+ *
+ * @param pb protobuf handle.
+ * @param field Field name.
+ * @return protobuf handle to added, embedded message.
+ * @error Invalid or incorrect Handle, non-existent field, or incorrect field type.
+ */
+native Handle:PbAddMessage(Handle:pb, const String:field[]);
diff --git a/sourcemod-1.5-dev/scripting/include/regex.inc b/sourcemod-1.5-dev/scripting/include/regex.inc
new file mode 100644
index 0000000..555c4a3
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/regex.inc
@@ -0,0 +1,186 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _regex_included
+ #endinput
+#endif
+#define _regex_included
+
+/**
+ * @section Flags for compiling regex expressions. These come directly from the
+ * pcre library and can be used in MatchRegex and CompileRegex.
+ */
+#define PCRE_CASELESS 0x00000001 /* Ignore Case */
+#define PCRE_MULTILINE 0x00000002 /* Multilines (affects ^ and $ so that they match the start/end of a line rather than matching the start/end of the string). */
+#define PCRE_DOTALL 0x00000004 /* Single line (affects . so that it matches any character, even new line characters). */
+#define PCRE_EXTENDED 0x00000008 /* Pattern extension (ignore whitespace and # comments). */
+#define PCRE_ANCHORED 0x00000010 /* Force pattern anchoring. */
+#define PCRE_DOLLAR_ENDONLY 0x00000020 /* $ not to match newline at end. */
+#define PCRE_UNGREEDY 0x00000200 /* Invert greediness of quantifiers */
+#define PCRE_NOTEMPTY 0x00000400 /* An empty string is not a valid match. */
+#define PCRE_UTF8 0x00000800 /* Use UTF-8 Chars */
+#define PCRE_NO_UTF8_CHECK 0x00002000 /* Do not check the pattern for UTF-8 validity (only relevant if PCRE_UTF8 is set) */
+#define PCRE_UCP 0x20000000 /* Use Unicode properties for \ed, \ew, etc. */
+
+
+/**
+ * Regex expression error codes.
+ */
+enum RegexError
+{
+ REGEX_ERROR_NONE = 0, /* No error */
+ REGEX_ERROR_NOMATCH = -1, /* No match was found */
+ REGEX_ERROR_NULL = -2,
+ REGEX_ERROR_BADOPTION = -3,
+ REGEX_ERROR_BADMAGIC = -4,
+ REGEX_ERROR_UNKNOWN_OPCODE = -5,
+ REGEX_ERROR_NOMEMORY = -6,
+ REGEX_ERROR_NOSUBSTRING = -7,
+ REGEX_ERROR_MATCHLIMIT = -8,
+ REGEX_ERROR_CALLOUT = -9, /* Never used by PCRE itself */
+ REGEX_ERROR_BADUTF8 = -10,
+ REGEX_ERROR_BADUTF8_OFFSET = -11,
+ REGEX_ERROR_PARTIAL = -12,
+ REGEX_ERROR_BADPARTIAL = -13,
+ REGEX_ERROR_INTERNAL = -14,
+ REGEX_ERROR_BADCOUNT = -15,
+ REGEX_ERROR_DFA_UITEM = -16,
+ REGEX_ERROR_DFA_UCOND = -17,
+ REGEX_ERROR_DFA_UMLIMIT = -18,
+ REGEX_ERROR_DFA_WSSIZE = -19,
+ REGEX_ERROR_DFA_RECURSE = -20,
+ REGEX_ERROR_RECURSIONLIMIT = -21,
+ REGEX_ERROR_NULLWSLIMIT = -22, /* No longer actually used */
+ REGEX_ERROR_BADNEWLINE = -23,
+ REGEX_ERROR_BADOFFSET = -24,
+ REGEX_ERROR_SHORTUTF8 = -25,
+ REGEX_ERROR_RECURSELOOP = -26,
+ REGEX_ERROR_JIT_STACKLIMIT = -27,
+ REGEX_ERROR_BADMODE = -28,
+ REGEX_ERROR_BADENDIANNESS = -29,
+ REGEX_ERROR_DFA_BADRESTART = -30,
+ REGEX_ERROR_JIT_BADOPTION = -31,
+ REGEX_ERROR_BADLENGTH = -32,
+};
+
+/**
+ * Precompile a regular expression. Use this if you intend on using the
+ * same expression multiple times. Pass the regex handle returned here to
+ * MatchRegex to check for matches.
+ *
+ * @param pattern The regular expression pattern.
+ * @param flags General flags for the regular expression.
+ * @param error Error message encountered, if applicable.
+ * @param maxLen Maximum string length of the error buffer.
+ * @param errcode Regex type error code encountered, if applicable.
+ * @return Valid regex handle on success, INVALID_HANDLE on failure.
+ */
+native Handle:CompileRegex(const String:pattern[], flags = 0, String:error[]="", maxLen = 0, &RegexError:errcode = REGEX_ERROR_NONE);
+
+/**
+ * Matches a string against a pre-compiled regular expression pattern.
+ *
+ * @param str The string to check.
+ * @param regex Regex Handle from CompileRegex()
+ * @param ret Error code, if applicable.
+ * @return Number of substrings found or -1 on failure.
+ *
+ * @note Use the regex handle passed to this function to extract
+ * matches with GetRegexSubString().
+ */
+native MatchRegex(Handle:regex, const String:str[], &RegexError:ret = REGEX_ERROR_NONE);
+
+/**
+ * Returns a matched substring from a regex handle.
+ * Substring ids start at 0 and end at substrings-1, where substrings is the number returned
+ * by MatchRegex
+ *
+ * @param regex The regex handle to extract data from.
+ * @param str_id The index of the expression to get - starts at 0, and ends at substrings - 1.
+ * @param buffer The buffer to set to the matching substring.
+ * @param maxlen The maximum string length of the buffer.
+ * @return True if a substring was found, False on fail/error
+ */
+native bool:GetRegexSubString(Handle:regex, str_id, String:buffer[], maxlen);
+
+/**
+ * Matches a string against a regular expression pattern.
+ *
+ * @note If you intend on using the same regular expression pattern
+ * multiple times, consider using CompileRegex and MatchRegex
+ * instead of making this function reparse the expression each time.
+ *
+ * @param str The string to check.
+ * @param pattern The regular expression pattern.
+ * @param flags General flags for the regular expression.
+ * @param error Error message, if applicable.
+ * @param maxLen Maximum length of the error buffer.
+ * @return Number of substrings found or -1 on failure.
+ */
+stock SimpleRegexMatch(const String:str[], const String:pattern[], flags = 0, String:error[]="", maxLen = 0)
+{
+ new Handle:regex = CompileRegex(pattern, flags, error, maxLen);
+
+ if (regex == INVALID_HANDLE)
+ {
+ return -1;
+ }
+
+ new substrings = MatchRegex(regex, str);
+
+ CloseHandle(regex);
+
+ return substrings;
+}
+
+/**
+ * @endsection
+ */
+
+/**
+ * Do not edit below this line!
+ */
+public Extension:__ext_regex =
+{
+ name = "Regex Extension",
+ file = "regex.ext",
+#if defined AUTOLOAD_EXTENSIONS
+ autoload = 1,
+#else
+ autoload = 0,
+#endif
+#if defined REQUIRE_EXTENSIONS
+ required = 1,
+#else
+ required = 0,
+#endif
+};
diff --git a/sourcemod-1.5-dev/scripting/include/sdkhooks.inc b/sourcemod-1.5-dev/scripting/include/sdkhooks.inc
new file mode 100644
index 0000000..2b25504
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdkhooks.inc
@@ -0,0 +1,394 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2009-2013 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ */
+
+#if defined _sdkhooks_included
+ #endinput
+#endif
+#define _sdkhooks_included
+
+// this is obviously _not_ a robust check, but it will solve most conflict and is clean
+#if !defined DMG_GENERIC
+#define DMG_GENERIC 0 /**< generic damage was done */
+#define DMG_CRUSH (1 << 0) /**< crushed by falling or moving object.
+ NOTE: It's assumed crush damage is occurring as a result of physics collision, so no extra physics force is generated by crush damage.
+ DON'T use DMG_CRUSH when damaging entities unless it's the result of a physics collision. You probably want DMG_CLUB instead. */
+#define DMG_BULLET (1 << 1) /**< shot */
+#define DMG_SLASH (1 << 2) /**< cut, clawed, stabbed */
+#define DMG_BURN (1 << 3) /**< heat burned */
+#define DMG_VEHICLE (1 << 4) /**< hit by a vehicle */
+#define DMG_FALL (1 << 5) /**< fell too far */
+#define DMG_BLAST (1 << 6) /**< explosive blast damage */
+#define DMG_CLUB (1 << 7) /**< crowbar, punch, headbutt */
+#define DMG_SHOCK (1 << 8) /**< electric shock */
+#define DMG_SONIC (1 << 9) /**< sound pulse shockwave */
+#define DMG_ENERGYBEAM (1 << 10) /**< laser or other high energy beam */
+#define DMG_PREVENT_PHYSICS_FORCE (1 << 11) /**< Prevent a physics force */
+#define DMG_NEVERGIB (1 << 12) /**< with this bit OR'd in, no damage type will be able to gib victims upon death */
+#define DMG_ALWAYSGIB (1 << 13) /**< with this bit OR'd in, any damage type can be made to gib victims upon death. */
+#define DMG_DROWN (1 << 14) /**< Drowning */
+#define DMG_PARALYZE (1 << 15) /**< slows affected creature down */
+#define DMG_NERVEGAS (1 << 16) /**< nerve toxins, very bad */
+#define DMG_POISON (1 << 17) /**< blood poisoning - heals over time like drowning damage */
+#define DMG_RADIATION (1 << 18) /**< radiation exposure */
+#define DMG_DROWNRECOVER (1 << 19) /**< drowning recovery */
+#define DMG_ACID (1 << 20) /**< toxic chemicals or acid burns */
+#define DMG_SLOWBURN (1 << 21) /**< in an oven */
+#define DMG_REMOVENORAGDOLL (1 << 22) /**< with this bit OR'd in, no ragdoll will be created, and the target will be quietly removed.
+ use this to kill an entity that you've already got a server-side ragdoll for */
+#define DMG_PHYSGUN (1 << 23) /**< Hit by manipulator. Usually doesn't do any damage. */
+#define DMG_PLASMA (1 << 24) /**< Shot by Cremator */
+#define DMG_AIRBOAT (1 << 25) /**< Hit by the airboat's gun */
+#define DMG_DISSOLVE (1 << 26) /**< Dissolving! */
+#define DMG_BLAST_SURFACE (1 << 27) /**< A blast on the surface of water that cannot harm things underwater */
+#define DMG_DIRECT (1 << 28)
+#define DMG_BUCKSHOT (1 << 29) /**< not quite a bullet. Little, rounder, different. */
+#endif
+
+#if !defined DMG_CRIT
+ // TF2 crits and minicrits
+ #define DMG_CRIT DMG_ACID
+#endif
+
+enum SDKHookType
+{
+ SDKHook_EndTouch,
+ SDKHook_FireBulletsPost,
+ SDKHook_OnTakeDamage,
+ SDKHook_OnTakeDamagePost,
+ SDKHook_PreThink,
+ SDKHook_PostThink,
+ SDKHook_SetTransmit,
+ SDKHook_Spawn,
+ SDKHook_StartTouch,
+ SDKHook_Think,
+ SDKHook_Touch,
+ SDKHook_TraceAttack,
+ SDKHook_TraceAttackPost,
+ SDKHook_WeaponCanSwitchTo,
+ SDKHook_WeaponCanUse,
+ SDKHook_WeaponDrop,
+ SDKHook_WeaponEquip,
+ SDKHook_WeaponSwitch,
+ SDKHook_ShouldCollide,
+ SDKHook_PreThinkPost,
+ SDKHook_PostThinkPost,
+ SDKHook_ThinkPost,
+ SDKHook_EndTouchPost,
+ SDKHook_GroundEntChangedPost,
+ SDKHook_SpawnPost,
+ SDKHook_StartTouchPost,
+ SDKHook_TouchPost,
+ SDKHook_VPhysicsUpdate,
+ SDKHook_VPhysicsUpdatePost,
+ SDKHook_WeaponCanSwitchToPost,
+ SDKHook_WeaponCanUsePost,
+ SDKHook_WeaponDropPost,
+ SDKHook_WeaponEquipPost,
+ SDKHook_WeaponSwitchPost,
+ SDKHook_Use,
+ SDKHook_UsePost,
+ SDKHook_Reload,
+ SDKHook_ReloadPost,
+ SDKHook_GetMaxHealth, /**< ep2v and later */
+};
+
+/*
+ Alphabetized for easy readability
+
+ SDKHook_EndTouch,
+ SDKHook_EndTouchPost,
+
+ SDKHook_FireBulletsPost,
+
+ SDKHook_GetMaxHealth, (ep2v and later)
+
+ SDKHook_GroundEntChangedPost,
+
+ SDKHook_OnTakeDamage,
+ SDKHook_OnTakeDamagePost,
+
+ SDKHook_PreThink,
+ SDKHook_PreThinkPost,
+
+ SDKHook_PostThink,
+ SDKHook_PostThinkPost,
+
+ SDKHook_Reload,
+ SDKHook_ReloadPost,
+
+ SDKHook_SetTransmit,
+
+ SDKHook_ShouldCollide,
+
+ SDKHook_Spawn,
+ SDKHook_SpawnPost,
+
+ SDKHook_StartTouch,
+ SDKHook_StartTouchPost,
+
+ SDKHook_Think,
+ SDKHook_ThinkPost,
+
+ SDKHook_Touch,
+ SDKHook_TouchPost,
+
+ SDKHook_TraceAttack,
+ SDKHook_TraceAttackPost,
+
+ SDKHook_Use,
+ SDKHook_UsePost,
+
+ SDKHook_VPhysicsUpdate,
+ SDKHook_VPhysicsUpdatePost,
+
+ SDKHook_WeaponCanSwitchTo,
+ SDKHook_WeaponCanSwitchToPost,
+
+ SDKHook_WeaponCanUse,
+ SDKHook_WeaponCanUsePost,
+
+ SDKHook_WeaponDrop,
+ SDKHook_WeaponDropPost,
+
+ SDKHook_WeaponEquip,
+ SDKHook_WeaponEquipPost,
+
+ SDKHook_WeaponSwitch,
+ SDKHook_WeaponSwitchPost
+*/
+
+enum UseType
+{
+ Use_Off,
+ Use_On,
+ Use_Set,
+ Use_Toggle
+};
+
+funcenum SDKHookCB
+{
+ // PreThink/Post
+ // PostThink/Post
+ public(client),
+
+ // Spawn
+ Action:public(entity),
+
+ // GroundEntChanged
+ // SpawnPost
+ // Think/Post
+ // VPhysicsUpdate/Post
+ public(entity),
+
+ // EndTouch
+ // StartTouch
+ // Touch
+ Action:public(entity, other),
+
+ // EndTouchPost
+ // StartTouchPost
+ // TouchPost
+ public(entity, other),
+
+ // SetTransmit
+ Action:public(entity, client),
+
+ // WeaponCanSwitchTo
+ // WeaponCanUse
+ // WeaponDrop
+ // WeaponEquip
+ // WeaponSwitch
+ Action:public(client, weapon),
+
+ // WeaponCanSwitchToPost
+ // WeaponCanUsePost
+ // WeaponDropPost
+ // WeaponEquipPost
+ // WeaponSwitchPost
+ public(client, weapon),
+
+ // GetMaxHealth (ep2v and later)
+ Action:public(entity, &maxhealth),
+
+ // OnTakeDamage
+ // Note: The weapon parameter is not used by all games and damage sources.
+ // Note: Force application is dependent on game and damage type(s)
+ // SDKHooks 1.0+
+ Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype),
+ // SDKHooks 2.0+
+ Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype, &weapon, Float:damageForce[3], Float:damagePosition[3]),
+ // SDKHooks 2.1+ (can check for support at runtime using GetFeatureStatus on SDKHook_DmgCustomInOTD capability.
+ // DON'T attempt to access 'damagecustom' var if feature status != available
+ Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype, &weapon,
+ Float:damageForce[3], Float:damagePosition[3], damagecustom),
+
+ // OnTakeDamagePost
+ public(victim, attacker, inflictor, Float:damage, damagetype),
+ public(victim, attacker, inflictor, Float:damage, damagetype, weapon, const Float:damageForce[3], const Float:damagePosition[3]),
+
+ // FireBulletsPost
+ public(client, shots, const String:weaponname[]),
+
+ // TraceAttack
+ Action:public(victim, &attacker, &inflictor, &Float:damage, &damagetype, &ammotype, hitbox, hitgroup),
+
+ // TraceAttackPost
+ public(victim, attacker, inflictor, Float:damage, damagetype, ammotype, hitbox, hitgroup),
+
+ // ShouldCollide
+ bool:public(entity, collisiongroup, contentsmask, bool:originalResult),
+
+ // Use
+ Action:public(entity, activator, caller, UseType:type, Float:value),
+
+ // UsePost
+ public(entity, activator, caller, UseType:type, Float:value),
+
+ // Reload
+ Action:public(weapon),
+
+ // Reload post
+ public(weapon, bool:bSuccessful)
+};
+
+
+/**
+ * @brief When an entity is created
+ *
+ * @param entity Entity index
+ * @param classname Class name
+ * @noreturn
+ */
+forward OnEntityCreated(entity, const String:classname[]);
+
+/**
+ * @brief When an entity is destroyed
+ *
+ * @param entity Entity index
+ * @noreturn
+ */
+forward OnEntityDestroyed(entity);
+
+/**
+ * @brief When the game description is retrieved
+ *
+ * @note Not supported on ep2v.
+ *
+ * @param gameDesc Game description
+ * @noreturn
+ */
+forward Action:OnGetGameDescription(String:gameDesc[64]);
+
+/**
+ * @brief When the level is initialized
+ *
+ * @param mapName Name of the map
+ * @param mapEntities Entities of the map
+ * @noreturn
+ */
+forward Action:OnLevelInit(const String:mapName[], String:mapEntities[2097152]);
+
+/**
+ * @brief Hooks an entity
+ *
+ * @param entity Entity index
+ * @param type Type of function to hook
+ * @param callback Function to call when hook is called
+ * @noreturn
+ */
+native SDKHook(entity, SDKHookType:type, SDKHookCB:callback);
+
+/**
+ * @brief Hooks an entity
+ *
+ * @param entity Entity index
+ * @param type Type of function to hook
+ * @param callback Function to call when hook is called
+ * @return bool Hook Successful
+ */
+native bool:SDKHookEx(entity, SDKHookType:type, SDKHookCB:callback);
+
+/**
+ * @brief Unhooks an entity
+ *
+ * @param entity Entity index
+ * @param type Type of function to unhook
+ * @param callback Callback function to unhook
+ * @noreturn
+ */
+native SDKUnhook(entity, SDKHookType:type, SDKHookCB:callback);
+
+/**
+ * @brief Applies damage to an entity
+ *
+ * @note Force application is dependent on game and damage type(s)
+ *
+ * @param entity Entity index taking damage
+ * @param inflictor Inflictor entity index
+ * @param attacker Attacker entity index
+ * @param damage Amount of damage
+ * @param damageType Bitfield of damage types
+ * @param weapon Weapon index (orangebox and later) or -1 for unspecified
+ * @param damageForce Velocity of damage force
+ * @param damagePosition Origin of damage
+ * @noreturn
+ */
+native SDKHooks_TakeDamage(entity, inflictor, attacker, Float:damage, damageType=DMG_GENERIC, weapon=-1, const Float:damageForce[3]=NULL_VECTOR, const Float:damagePosition[3]=NULL_VECTOR);
+
+/**
+ * @brief Forces a client to drop the specified weapon
+ *
+ * @param client Client index.
+ * @param weapon Weapon entity index.
+ * @param vecTarget Location to toss weapon to, or NULL_VECTOR for default.
+ * @param vecVelocity Velocity at which to toss weapon, or NULL_VECTOR for default.
+ * @noreturn
+ * @error Invalid client or weapon entity, weapon not owned by client.
+ */
+native SDKHooks_DropWeapon(client, weapon, const Float:vecTarget[3]=NULL_VECTOR, const Float:vecVelocity[3]=NULL_VECTOR);
+
+/**
+ * Do not edit below this line!
+ */
+public Extension:__ext_sdkhooks =
+{
+ name = "SDKHooks",
+ file = "sdkhooks.ext",
+#if defined AUTOLOAD_EXTENSIONS
+ autoload = 1,
+#else
+ autoload = 0,
+#endif
+#if defined REQUIRE_EXTENSIONS
+ required = 1,
+#else
+ required = 0,
+#endif
+};
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools.inc b/sourcemod-1.5-dev/scripting/include/sdktools.inc
new file mode 100644
index 0000000..3351bcf
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools.inc
@@ -0,0 +1,232 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_included
+ #endinput
+#endif
+#define _sdktools_included
+
+#include <core>
+#include <sdktools_engine>
+#include <sdktools_functions>
+#if !defined SDKTOOLS_DISABLE_SOUNDAPI
+#include <sdktools_sound>
+#endif
+#include <sdktools_stringtables>
+#include <sdktools_trace>
+#include <sdktools_tempents>
+#include <sdktools_tempents_stocks>
+#include <sdktools_voice>
+#include <sdktools_entinput>
+#include <sdktools_entoutput>
+#include <sdktools_hooks>
+#include <sdktools_gamerules>
+#include <sdktools_client>
+
+enum SDKCallType
+{
+ SDKCall_Static, /**< Static call */
+ SDKCall_Entity, /**< CBaseEntity call */
+ SDKCall_Player, /**< CBasePlayer call */
+ SDKCall_GameRules, /**< CGameRules call */
+ SDKCall_EntityList, /**< CGlobalEntityList call */
+ SDKCall_Raw, /**< |this| pointer with an arbitrary address */
+};
+
+enum SDKLibrary
+{
+ SDKLibrary_Server, /**< server.dll/server_i486.so */
+ SDKLibrary_Engine, /**< engine.dll/engine_*.so */
+};
+
+enum SDKFuncConfSource
+{
+ SDKConf_Virtual = 0, /**< Read a virtual index from the Offsets section */
+ SDKConf_Signature = 1, /**< Read a signature from the Signatures section */
+ SDKConf_Address = 2, /**< Read an address from the Addresses section */
+};
+
+enum SDKType
+{
+ SDKType_CBaseEntity, /**< CBaseEntity (always as pointer) */
+ SDKType_CBasePlayer, /**< CBasePlayer (always as pointer) */
+ SDKType_Vector, /**< Vector (pointer, byval, or byref) */
+ SDKType_QAngle, /**< QAngles (pointer, byval, or byref) */
+ SDKType_PlainOldData, /**< Integer/generic data <=32bit (any) */
+ SDKType_Float, /**< Float (any) */
+ SDKType_Edict, /**< edict_t (always as pointer) */
+ SDKType_String, /**< NULL-terminated string (always as pointer) */
+ SDKType_Bool, /**< Boolean (any) */
+};
+
+enum SDKPassMethod
+{
+ SDKPass_Pointer, /**< Pass as a pointer */
+ SDKPass_Plain, /**< Pass as plain data */
+ SDKPass_ByValue, /**< Pass an object by value */
+ SDKPass_ByRef, /**< Pass an object by reference */
+};
+
+#define VDECODE_FLAG_ALLOWNULL (1<<0) /**< Allow NULL for pointers */
+#define VDECODE_FLAG_ALLOWNOTINGAME (1<<1) /**< Allow players not in game */
+#define VDECODE_FLAG_ALLOWWORLD (1<<2) /**< Allow World entity */
+#define VDECODE_FLAG_BYREF (1<<3) /**< Floats/ints by reference */
+
+#define VENCODE_FLAG_COPYBACK (1<<0) /**< Copy back data once done */
+
+/**
+ * Starts the preparation of an SDK call.
+ *
+ * @param type Type of function call this will be.
+ * @noreturn
+ */
+native StartPrepSDKCall(SDKCallType:type);
+
+/**
+ * Sets the virtual index of the SDK call if it is virtual.
+ *
+ * @param vtblidx Virtual table index.
+ * @noreturn
+ */
+native PrepSDKCall_SetVirtual(vtblidx);
+
+/**
+ * Finds an address in a library and sets it as the address to use for the SDK call.
+ *
+ * @param lib Library to use.
+ * @param signature Binary data to search for in the library. If it starts with '@',
+ * the bytes parameter is ignored and the signature is interpreted
+ * as a symbol lookup in the library.
+ * @param bytes Number of bytes in the binary search string.
+ * @return True on success, false if nothing was found.
+ */
+native bool:PrepSDKCall_SetSignature(SDKLibrary:lib, const String:signature[], bytes);
+
+/**
+ * Uses the given function address for the SDK call.
+ *
+ * @param addr Address of function to use.
+ * @return True on success, false on failure.
+ */
+native bool:PrepSDKCall_SetAddress(Address:addr);
+
+/**
+ * Finds an address or virtual function index in a GameConfig file and sets it as
+ * the calling information for the SDK call.
+ *
+ * @param gameconf GameConfig Handle, or INVALID_HANDLE to use sdktools.games.txt.
+ * @param source Whether to look in Offsets or Signatures.
+ * @param name Name of the property to find.
+ * @return True on success, false if nothing was found.
+ */
+native bool:PrepSDKCall_SetFromConf(Handle:gameconf, SDKFuncConfSource:source, const String:name[]);
+
+/**
+ * Sets the return information of an SDK call. Do not call this if there is no return data.
+ * This must be called if there is a return value (i.e. it is not necessarily safe to ignore
+ * the data).
+ *
+ * @param type Data type to convert to/from.
+ * @param pass How the data is passed in C++.
+ * @param decflags Flags on decoding from the plugin to C++.
+ * @param encflags Flags on encoding from C++ to the plugin.
+ * @noreturn
+ */
+native PrepSDKCall_SetReturnInfo(SDKType:type, SDKPassMethod:pass, decflags=0, encflags=0);
+
+/**
+ * Adds a parameter to the calling convention. This should be called in normal ascending order.
+ *
+ * @param type Data type to convert to/from.
+ * @param pass How the data is passed in C++.
+ * @param decflags Flags on decoding from the plugin to C++.
+ * @param encflags Flags on encoding from C++ to the plugin.
+ * @noreturn
+ */
+native PrepSDKCall_AddParameter(SDKType:type, SDKPassMethod:pass, decflags=0, encflags=0);
+
+/**
+ * Finalizes an SDK call preparation and returns the resultant Handle.
+ *
+ * @return A new SDKCall Handle on success, or INVALID_HANDLE on failure.
+ */
+native Handle:EndPrepSDKCall();
+
+/**
+ * Calls an SDK function with the given parameters.
+ *
+ * If the call type is Entity or Player, the index MUST ALWAYS be the FIRST parameter passed.
+ * If the call type is GameRules, then nothing special needs to be passed.
+ * If the return value is a Vector or QAngles, the SECOND parameter must be a Float[3].
+ * If the return value is a string, the THIRD parameter must be a String buffer, and the
+ * FOURTH parameter must be the maximum length.
+ * All parameters must be passed after the above is followed. Failure to follow these
+ * rules will result in crashes or wildly unexpected behavior!
+ *
+ * If the return value is a float or integer, the return value will be this value.
+ * If the return value is a CBaseEntity, CBasePlayer, or edict, the return value will
+ * always be the entity index, or -1 for NULL.
+ *
+ * @param call SDKCall Handle.
+ * @param ... Call Parameters.
+ * @return Simple return value, if any.
+ * @error Invalid Handle or internal decoding error.
+ */
+native any:SDKCall(Handle:call, any:...);
+
+/**
+ * Returns the entity index of the player resource/manager entity.
+ *
+ * @return Index of resource entity or -1 if not found.
+ */
+native GetPlayerResourceEntity();
+
+#include <sdktools_stocks>
+
+/**
+ * Do not edit below this line!
+ */
+public Extension:__ext_sdktools =
+{
+ name = "SDKTools",
+ file = "sdktools.ext",
+#if defined AUTOLOAD_EXTENSIONS
+ autoload = 1,
+#else
+ autoload = 0,
+#endif
+#if defined REQUIRE_EXTENSIONS
+ required = 1,
+#else
+ required = 0,
+#endif
+};
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_client.inc b/sourcemod-1.5-dev/scripting/include/sdktools_client.inc
new file mode 100644
index 0000000..02dfcfd
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_client.inc
@@ -0,0 +1,52 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_client_included
+ #endinput
+#endif
+#define _sdktools_client_included
+
+/**
+ * Sets the client to an inactive state waiting for a new map
+ *
+ * @param client The client index
+ * @noreturn
+ */
+native InactivateClient(client);
+
+/**
+ * Reconnect a client without dropping the netchannel
+ *
+ * @param client The client index
+ * @noreturn
+ */
+native ReconnectClient(client);
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_engine.inc b/sourcemod-1.5-dev/scripting/include/sdktools_engine.inc
new file mode 100644
index 0000000..a34439e
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_engine.inc
@@ -0,0 +1,69 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_engine_included
+ #endinput
+#endif
+#define _sdktools_engine_included
+
+#define MAX_LIGHTSTYLES 64
+
+/**
+ * Sets a client's "viewing entity."
+ *
+ * @param client Client index.
+ * @param entity Entity index.
+ * @noreturn
+ * @error Invalid client or entity, lack of mod support, or client not in
+ * game.
+ */
+native SetClientViewEntity(client, entity);
+
+/**
+ * Sets a light style.
+ *
+ * @param style Light style (from 0 to MAX_LIGHTSTYLES-1)
+ * @param value Light value string (see world.cpp/light.cpp in dlls)
+ * @noreturn
+ * @error Light style index is out of range.
+ */
+native SetLightStyle(style, const String:value[]);
+
+/**
+ * Returns the client's eye position.
+ *
+ * @param client Player's index.
+ * @param pos Destination vector to store the client's eye position.
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native GetClientEyePosition(client, Float:pos[3]);
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_entinput.inc b/sourcemod-1.5-dev/scripting/include/sdktools_entinput.inc
new file mode 100644
index 0000000..88d90cc
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_entinput.inc
@@ -0,0 +1,116 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_entinput_included
+ #endinput
+#endif
+#define _sdktools_entinput_included
+
+/**
+ * Invokes a named input method on an entity.
+ *
+ * After completion (successful or not), the current global variant is re-initalized.
+ *
+ * @param dest Destination entity index.
+ * @param input Input action.
+ * @param activator Entity index which initiated the sequence of actions (-1 for a NULL entity).
+ * @param caller Entity index from which this event is sent (-1 for a NULL entity).
+ * @param outputid Unknown.
+ * @return True if successful otherwise false.
+ * @error Invalid entity index or no mod support.
+ */
+native bool:AcceptEntityInput(dest, const String:input[], activator=-1, caller=-1, outputid=0);
+
+/**
+ * Sets a bool value in the global variant object.
+ *
+ * @param val Input value.
+ * @noreturn
+ */
+native SetVariantBool(bool:val);
+
+/**
+ * Sets a string in the global variant object.
+ *
+ * @param str Input string.
+ * @noreturn
+ */
+native SetVariantString(const String:str[]);
+
+/**
+ * Sets an integer value in the global variant object.
+ *
+ * @param val Input value.
+ * @noreturn
+ */
+native SetVariantInt(val);
+
+/**
+ * Sets a floating point value in the global variant object.
+ *
+ * @param val Input value.
+ * @noreturn
+ */
+native SetVariantFloat(Float:val);
+
+/**
+ * Sets a 3D vector in the global variant object.
+ *
+ * @param vec Input vector.
+ * @noreturn
+ */
+native SetVariantVector3D(const Float:vec[3]);
+
+/**
+ * Sets a 3D position vector in the global variant object.
+ *
+ * @param vec Input position vector.
+ * @noreturn
+ */
+native SetVariantPosVector3D(const Float:vec[3]);
+
+/**
+ * Sets a color in the global variant object.
+ *
+ * @param color Input color.
+ * @noreturn
+ */
+native SetVariantColor(const color[4]);
+
+/**
+ * Sets an entity in the global variant object.
+ *
+ * @param entity Entity index.
+ * @noreturn
+ * @error Invalid entity index.
+ */
+native SetVariantEntity(entity);
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_entoutput.inc b/sourcemod-1.5-dev/scripting/include/sdktools_entoutput.inc
new file mode 100644
index 0000000..b7aeaaa
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_entoutput.inc
@@ -0,0 +1,91 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_entoutput_included
+ #endinput
+#endif
+#define _sdktools_entoutput_included
+
+/**
+ * Called when an entity output is fired.
+ *
+ * @param output Name of the output that fired.
+ * @param caller Entity index of the caller.
+ * @param activator Entity index of the activator.
+ * @param delay Delay in seconds? before the event gets fired.
+ */
+functag public EntityOutput(const String:output[], caller, activator, Float:delay);
+
+/**
+ * Add an entity output hook on a entity classname
+ *
+ * @param classname The classname to hook.
+ * @param output The output name to hook.
+ * @param callback An EntityOutput function pointer.
+ * @noreturn
+ * @error Entity Outputs disabled.
+ */
+native HookEntityOutput(const String:classname[], const String:output[], EntityOutput:callback);
+
+/**
+ * Remove an entity output hook.
+ * @param classname The classname to hook.
+ * @param output The output name to hook.
+ * @param callback An EntityOutput function pointer.
+ * @return True on success, false if no valid hook was found.
+ * @error Entity Outputs disabled.
+ */
+native bool:UnhookEntityOutput(const String:classname[], const String:output[], EntityOutput:callback);
+
+/**
+ * Add an entity output hook on a single entity instance
+ *
+ * @param entity The entity on which to add a hook.
+ * @param output The output name to hook.
+ * @param callback An EntityOutput function pointer.
+ * @param once Only fire this hook once and then remove itself.
+ * @noreturn
+ * @error Entity Outputs disabled or Invalid Entity index.
+ */
+native HookSingleEntityOutput(entity, const String:output[], EntityOutput:callback , bool:once=false);
+
+/**
+ * Remove a single entity output hook.
+ *
+ * @param entity The entity on which to remove the hook.
+ * @param output The output name to hook.
+ * @param callback An EntityOutput function pointer.
+ * @return True on success, false if no valid hook was found.
+ * @error Entity Outputs disabled or Invalid Entity index.
+ */
+native bool:UnhookSingleEntityOutput(entity, const String:output[], EntityOutput:callback);
+
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_functions.inc b/sourcemod-1.5-dev/scripting/include/sdktools_functions.inc
new file mode 100644
index 0000000..16b3e47
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_functions.inc
@@ -0,0 +1,346 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_functions_included
+ #endinput
+#endif
+#define _sdktools_functions_included
+
+/**
+ * Removes a player's item.
+ *
+ * @param client Client index.
+ * @param item CBaseCombatWeapon entity index.
+ * @return True on success, false otherwise.
+ * @error Invalid client or entity, lack of mod support, or client not in
+ * game.
+ */
+native bool:RemovePlayerItem(client, item);
+
+/**
+ * Gives a named item to a player.
+ *
+ * @param client Client index.
+ * @param item Item classname (such as weapon_ak47).
+ * @param iSubType Unknown.
+ * @return Entity index on success, or -1 on failure.
+ * @error Invalid client or client not in game, or lack of mod support.
+ */
+native GivePlayerItem(client, const String:item[], iSubType=0);
+
+/**
+ * Returns the weapon in a player's slot.
+ *
+ * @param client Client index.
+ * @param slot Slot index (mod specific).
+ * @return Entity index on success, -1 if no weapon existed.
+ * @error Invalid client or client not in game, or lack of mod support.
+ */
+native GetPlayerWeaponSlot(client, slot);
+
+/**
+ * Ignites an entity on fire.
+ *
+ * @param entity Entity index.
+ * @param time Number of seconds to set on fire.
+ * @param npc True to only affect NPCs.
+ * @param size Unknown.
+ * @param level Unknown.
+ * @noreturn
+ * @error Invalid entity or client not in game, or lack of mod support.
+ */
+native IgniteEntity(entity, Float:time, bool:npc=false, Float:size=0.0, bool:level=false);
+
+/**
+ * Extinguishes an entity that is on fire.
+ *
+ * @param entity Entity index.
+ * @noreturn
+ * @error Invalid entity or client not in game, or lack of mod support.
+ */
+native ExtinguishEntity(entity);
+
+/**
+ * Teleports an entity.
+ *
+ * @param entity Client index.
+ * @param origin New origin, or NULL_VECTOR for no change.
+ * @param angles New angles, or NULL_VECTOR for no change.
+ * @param velocity New velocity, or NULL_VECTOR for no change.
+ * @noreturn
+ * @error Invalid entity or client not in game, or lack of mod support.
+ */
+native TeleportEntity(entity, const Float:origin[3], const Float:angles[3], const Float:velocity[3]);
+
+/**
+ * Forces a player to commit suicide.
+ *
+ * @param client Client index.
+ * @noreturn
+ * @error Invalid client or client not in game, or lack of mod support.
+ */
+native ForcePlayerSuicide(client);
+
+/**
+ * Slaps a player in a random direction.
+ *
+ * @param client Client index.
+ * @param health Health to subtract.
+ * @param sound False to disable the sound effects.
+ * @noreturn
+ * @error Invalid client or client not in game, or lack of mod support.
+ */
+native SlapPlayer(client, health=5, bool:sound=true);
+
+/**
+ * Searches for an entity by classname.
+ *
+ * @param startEnt The entity index after which to begin searching from.
+ * Use -1 to start from the first entity.
+ * @param classname Classname of the entity to find.
+ * @return Entity index >= 0 if found, -1 otherwise.
+ * @error Lack of mod support.
+ */
+native FindEntityByClassname(startEnt, const String:classname[]);
+
+/**
+ * Returns the client's eye angles.
+ *
+ * @param client Player's index.
+ * @param ang Destination vector to store the client's eye angles.
+ * @return True on success, false on failure.
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native bool:GetClientEyeAngles(client, Float:ang[3]);
+
+/**
+ * Creates an entity by string name, but does not spawn it (see DispatchSpawn).
+ * If ForceEdictIndex is not -1, then it will use the edict by that index. If the index is
+ * invalid or there is already an edict using that index, it will error out.
+ *
+ * @param classname Entity classname.
+ * @param ForceEdictIndex Edict index used by the created entity (ignored on Orangebox and above).
+ * @return Entity index on success, or -1 on failure.
+ * @error Invalid edict index, or no mod support.
+ */
+native CreateEntityByName(const String:classname[], ForceEdictIndex=-1);
+
+/**
+ * Spawns an entity into the game.
+ *
+ * @param entity Entity index of the created entity.
+ * @return True on success, false otherwise.
+ * @error Invalid entity index, or no mod support.
+ */
+native bool:DispatchSpawn(entity);
+
+/**
+ * Dispatches a KeyValue into given entity using a string value.
+ *
+ * @param entity Destination entity index.
+ * @param keyName Name of the key.
+ * @param value String value.
+ * @return True on success, false otherwise.
+ * @error Invalid entity index, or no mod support.
+ */
+native bool:DispatchKeyValue(entity, const String:keyName[], const String:value[]);
+
+/**
+ * Dispatches a KeyValue into given entity using a floating point value.
+ *
+ * @param entity Destination entity index.
+ * @param keyName Name of the key.
+ * @param value Floating point value.
+ * @return True on success, false otherwise.
+ * @error Invalid entity index, or no mod support.
+ */
+native bool:DispatchKeyValueFloat(entity, const String:keyName[], Float:value);
+
+/**
+ * Dispatches a KeyValue into given entity using a vector value.
+ *
+ * @param entity Destination entity index.
+ * @param keyName Name of the key.
+ * @param vec Vector value.
+ * @return True on success, false otherwise.
+ * @error Invalid entity index, or no mod support.
+ */
+native bool:DispatchKeyValueVector(entity, const String:keyName[], const Float:vec[3]);
+
+/**
+ * Returns the entity a client is aiming at.
+ *
+ * @param client Client performing the aiming.
+ * @param only_clients True to exclude all entities but clients.
+ * @return Entity index being aimed at.
+ * -1 if no entity is being aimed at.
+ * -2 if the function is not supported.
+ * @error Invalid client index or client not in game.
+ */
+native GetClientAimTarget(client, bool:only_clients=true);
+
+/**
+ * Returns the total number of teams in a game.
+ * Note: This native should not be called before OnMapStart.
+ *
+ * @return Total number of teams.
+ */
+native GetTeamCount();
+
+/**
+ * Retrieves the team name based on a team index.
+ * Note: This native should not be called before OnMapStart.
+ *
+ * @param index Team index.
+ * @param name Buffer to store string in.
+ * @param maxlength Maximum length of string buffer.
+ * @noreturn
+ * @error Invalid team index.
+ */
+native GetTeamName(index, String:name[], maxlength);
+
+/**
+ * Returns the score of a team based on a team index.
+ * Note: This native should not be called before OnMapStart.
+ *
+ * @param index Team index.
+ * @return Score.
+ * @error Invalid team index.
+ */
+native GetTeamScore(index);
+
+/**
+ * Sets the score of a team based on a team index.
+ * Note: This native should not be called before OnMapStart.
+ *
+ * @param index Team index.
+ * @param value New score value.
+ * @return Score.
+ * @error Invalid team index.
+ */
+native SetTeamScore(index, value);
+
+/**
+ * Retrieves the number of players in a certain team.
+ * Note: This native should not be called before OnMapStart.
+ *
+ * @param index Team index.
+ * @return Number of players in the team.
+ * @error Invalid team index.
+ */
+native GetTeamClientCount(index);
+
+/**
+ * Sets the model to a given entity.
+ *
+ * @param entity Entity index.
+ * @param model Model name.
+ * @noreturn
+ * @error Invalid entity index, or no mod support.
+ */
+native SetEntityModel(entity, const String:model[]);
+
+/**
+ * Retrieves the decal file name associated with a given client.
+ *
+ * @param client Player's index.
+ * @param hex Buffer to store the logo filename.
+ * @param maxlength Maximum length of string buffer.
+ * @return True on success, otherwise false.
+ * @error Invalid client or client not in game.
+ */
+native bool:GetPlayerDecalFile(client, String:hex[], maxlength);
+
+/**
+ * Retrieves the jingle file name associated with a given client.
+ *
+ * @param client Player's index.
+ * @param hex Buffer to store the jingle filename.
+ * @param maxlength Maximum length of string buffer.
+ * @return True on success, otherwise false.
+ * @error Invalid client or client not in game.
+ */
+native bool:GetPlayerJingleFile(client, String:hex[], maxlength);
+
+/**
+ * Returns the average server network traffic in bytes/sec.
+ *
+ * @param in Buffer to store the input traffic velocity.
+ * @param out Buffer to store the output traffic velocity.
+ * @noreturn
+ */
+native GetServerNetStats(&Float:in, &Float:out);
+
+/**
+ * Equip's a player's weapon.
+ *
+ * @param client Client index.
+ * @param weapon CBaseCombatWeapon entity index.
+ * @noreturn
+ * @error Invalid client or entity, lack of mod support, or client not in
+ * game.
+ */
+native EquipPlayerWeapon(client, weapon);
+
+/**
+ * Activates an entity (CBaseAnimating::Activate)
+ *
+ * @param entity Entity index.
+ * @noreturn
+ * @error Invalid entity or lack of mod support.
+ */
+native ActivateEntity(entity);
+
+/**
+ * Sets values to client info buffer keys and notifies the engine of the change.
+ * The change does not get propogated to mods until the next frame.
+ *
+ * @param client Player's index.
+ * @param key Key string.
+ * @param value Value string.
+ * @noreturn
+ * @error Invalid client index, or client not connected.
+ */
+native SetClientInfo(client, const String:key[], const String:value[]);
+
+/**
+ * Gives ammo of a certain type to a player.
+ * This natives obeys the maximum amount of ammo a player can carry per ammo type.
+ *
+ * @param client The client index.
+ * @param amount Amount of ammo to give. Is capped at ammotype's limit.
+ * @param ammotype Type of ammo to give to player.
+ * @param suppressSound If true, don't play the ammo pickup sound.
+ *
+ * @return Amount of ammo actually given.
+ */
+native GivePlayerAmmo(client, amount, ammotype, bool:suppressSound=false); \ No newline at end of file
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_gamerules.inc b/sourcemod-1.5-dev/scripting/include/sdktools_gamerules.inc
new file mode 100644
index 0000000..6a5f7ba
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_gamerules.inc
@@ -0,0 +1,202 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2011 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_gamerules_included
+ #endinput
+#endif
+#define _sdktools_gamerules_included
+
+enum RoundState {
+ // initialize the game, create teams
+ RoundState_Init,
+
+ //Before players have joined the game. Periodically checks to see if enough players are ready
+ //to start a game. Also reverts to this when there are no active players
+ RoundState_Pregame,
+
+ //The game is about to start, wait a bit and spawn everyone
+ RoundState_StartGame,
+
+ //All players are respawned, frozen in place
+ RoundState_Preround,
+
+ //Round is on, playing normally
+ RoundState_RoundRunning,
+
+ //Someone has won the round
+ RoundState_TeamWin,
+
+ //Noone has won, manually restart the game, reset scores
+ RoundState_Restart,
+
+ //Noone has won, restart the game
+ RoundState_Stalemate,
+
+ //Game is over, showing the scoreboard etc
+ RoundState_GameOver,
+
+ //Game is over, doing bonus round stuff
+ RoundState_Bonus,
+
+ //Between rounds
+ RoundState_BetweenRounds,
+};
+
+/**
+ * Retrieves an integer value from a property of the gamerules entity.
+ *
+ * @param prop Property name.
+ * @param size Number of bytes to read (valid values are 1, 2, or 4).
+ * This value is auto-detected, and the size parameter is
+ * only used as a fallback in case detection fails.
+ * @param element Element # (starting from 0) if property is an array.
+ * @return Value at the given property offset.
+ * @error Not supported.
+ */
+native GameRules_GetProp(const String:prop[], size=4, element=0);
+
+/**
+ * Sets an integer value for a property of the gamerules entity.
+ *
+ * @param prop Property name.
+ * @param value Value to set.
+ * @param size Number of bytes to write (valid values are 1, 2, or 4).
+ * This value is auto-detected, and the size parameter is
+ * only used as a fallback in case detection fails.
+ * @param element Element # (starting from 0) if property is an array.
+ * @param changeState If true, change will be sent over the network.
+ * @error Not supported.
+ * @noreturn
+ */
+native GameRules_SetProp(const String:prop[], any:value, size=4, element=0, bool:changeState=false);
+
+/**
+ * Retrieves a float value from a property of the gamerules entity.
+ *
+ * @param prop Property name.
+ * @param element Element # (starting from 0) if property is an array.
+ * @return Value at the given property offset.
+ * @error Not supported.
+ */
+native Float:GameRules_GetPropFloat(const String:prop[], element=0);
+
+/**
+ * Sets a float value for a property of the gamerules entity.
+ *
+ * @param prop Property name.
+ * @param value Value to set.
+ * @param element Element # (starting from 0) if property is an array.
+ * @param changeState If true, change will be sent over the network.
+ * @noreturn
+ * @error Not supported.
+ */
+native GameRules_SetPropFloat(const String:prop[], Float:value, element=0, bool:changeState=false);
+
+/**
+ * Retrieves a entity index from a property of the gamerules entity.
+ *
+ * @param prop Property name.
+ * @param element Element # (starting from 0) if property is an array.
+ * @return Entity index at the given property.
+ * If there is no entity, or the entity is not valid,
+ * then -1 is returned.
+ * @error Not supported.
+ */
+native GameRules_GetPropEnt(const String:prop[], element=0);
+
+/**
+ * Sets an entity index for a property of the gamerules entity.
+ *
+ * @param prop Property name.
+ * @param other Entity index to set, or -1 to unset.
+ * @param element Element # (starting from 0) if property is an array.
+ * @param changeState If true, change will be sent over the network.
+ * @noreturn
+ * @error Not supported.
+ */
+native GameRules_SetPropEnt(const String:prop[], other, element=0, bool:changeState=false);
+
+/**
+ * Retrieves a vector of floats from the gamerules entity, given a named network property.
+ *
+ * @param prop Property name.
+ * @param vec Vector buffer to store data in.
+ * @param element Element # (starting from 0) if property is an array.
+ * @noreturn
+ * @error Not supported.
+ */
+native GameRules_GetPropVector(const String:prop[], Float:vec[3], element=0);
+
+/**
+ * Sets a vector of floats in the gamerules entity, given a named network property.
+ *
+ * @param prop Property name.
+ * @param vec Vector to set.
+ * @param element Element # (starting from 0) if property is an array.
+ * @param changeState If true, change will be sent over the network.
+ * @noreturn
+ * @error Not supported.
+ */
+native GameRules_SetPropVector(const String:prop[], const Float:vec[3], element=0, bool:changeState=false);
+
+/**
+ * Gets a gamerules property as a string.
+ *
+ * @param prop Property to use.
+ * @param buffer Destination string buffer.
+ * @param maxlen Maximum length of output string buffer.
+ * @return Number of non-null bytes written.
+ * @error Not supported.
+ */
+native GameRules_GetPropString(const String:prop[], String:buffer[], maxlen);
+
+/**
+ * Sets a gamerules property as a string.
+ *
+ * @param prop Property to use.
+ * @param buffer String to set.
+ * @param changeState If true, change will be sent over the network.
+ * @return Number of non-null bytes written.
+ * @error Not supported.
+ */
+native GameRules_SetPropString(const String:prop[], const String:buffer[], bool:changeState=false);
+
+/**
+ * Gets the current round state.
+ *
+ * @return Round state.
+ * @error Game doesn't support round state.
+ */
+stock RoundState:GameRules_GetRoundState()
+{
+ return RoundState:GameRules_GetProp("m_iRoundState");
+}
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_hooks.inc b/sourcemod-1.5-dev/scripting/include/sdktools_hooks.inc
new file mode 100644
index 0000000..bae8d52
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_hooks.inc
@@ -0,0 +1,59 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2009 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_hooks_included
+ #endinput
+#endif
+#define _sdktools_hooks_included
+
+#define FEATURECAP_PLAYERRUNCMD_11PARAMS "SDKTools PlayerRunCmd 11Params"
+
+/**
+ * @brief Called when a clients movement buttons are being processed
+ *
+ * @param client Index of the client.
+ * @param buttons Copyback buffer containing the current commands (as bitflags - see entity_prop_stocks.inc).
+ * @param impulse Copyback buffer containing the current impulse command.
+ * @param vel Players desired velocity.
+ * @param angles Players desired view angles.
+ * @param weapon Entity index of the new weapon if player switches weapon, 0 otherwise.
+ * @param subtype Weapon subtype when selected from a menu.
+ * @param cmdnum Command number. Increments from the first command sent.
+ * @param tickcount Tick count. A client's prediction based on the server's GetGameTickCount value.
+ * @param seed Random seed. Used to determine weapon recoil, spread, and other predicted elements.
+ * @param mouse Mouse direction (x, y).
+ * @return Plugin_Handled to block the commands from being processed, Plugin_Continue otherwise.
+ *
+ * @note To see if all 11 params are avaliable, use FeatureType_Capability and
+ * FEATURECAP_PLAYERRUNCMD_11PARAMS.
+ */
+forward Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon, &subtype, &cmdnum, &tickcount, &seed, mouse[2]); \ No newline at end of file
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_sound.inc b/sourcemod-1.5-dev/scripting/include/sdktools_sound.inc
new file mode 100644
index 0000000..bfb4e3f
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_sound.inc
@@ -0,0 +1,450 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_sound_included
+ #endinput
+#endif
+#define _sdktools_sound_included
+
+/**
+ * Sound should be from the target client.
+ */
+#define SOUND_FROM_PLAYER -2
+
+/**
+ * Sound should be from the listen server player.
+ */
+#define SOUND_FROM_LOCAL_PLAYER -1
+
+/**
+ * Sound is from the world.
+ */
+#define SOUND_FROM_WORLD 0
+
+/**
+ * Sound channels.
+ */
+enum
+{
+ SNDCHAN_REPLACE = -1, /**< Unknown */
+ SNDCHAN_AUTO = 0, /**< Auto */
+ SNDCHAN_WEAPON = 1, /**< Weapons */
+ SNDCHAN_VOICE = 2, /**< Voices */
+ SNDCHAN_ITEM = 3, /**< Items */
+ SNDCHAN_BODY = 4, /**< Player? */
+ SNDCHAN_STREAM = 5, /**< "Stream channel from the static or dynamic area" */
+ SNDCHAN_STATIC = 6, /**< "Stream channel from the static area" */
+ SNDCHAN_VOICE_BASE = 7, /**< "Channel for network voice data" */
+ SNDCHAN_USER_BASE = 135 /**< Anything >= this is allocated to game code */
+};
+
+/**
+ * Sound flags for the sound emitter system.
+ */
+enum
+{
+ SND_NOFLAGS= 0, /**< Nothing */
+ SND_CHANGEVOL = 1, /**< Change sound volume */
+ SND_CHANGEPITCH = 2, /**< Change sound pitch */
+ SND_STOP = 3, /**< Stop the sound */
+ SND_SPAWNING = 4, /**< Used in some cases for ambients */
+ SND_DELAY = 5, /**< Sound has an initial delay */
+ SND_STOPLOOPING = 6, /**< Stop looping all sounds on the entity */
+ SND_SPEAKER = 7, /**< Being played by a mic through a speaker */
+ SND_SHOULDPAUSE = 8, /**< Pause if game is paused */
+};
+
+/**
+ * Various predefined sound levels in dB.
+ */
+enum
+{
+ SNDLEVEL_NONE = 0, /**< None */
+ SNDLEVEL_RUSTLE = 20, /**< Rustling leaves */
+ SNDLEVEL_WHISPER = 25, /**< Whispering */
+ SNDLEVEL_LIBRARY = 30, /**< In a library */
+ SNDLEVEL_FRIDGE = 45, /**< Refridgerator */
+ SNDLEVEL_HOME = 50, /**< Average home (3.9 attn) */
+ SNDLEVEL_CONVO = 60, /**< Normal conversation (2.0 attn) */
+ SNDLEVEL_DRYER = 60, /**< Clothes dryer */
+ SNDLEVEL_DISHWASHER = 65, /**< Dishwasher/washing machine (1.5 attn) */
+ SNDLEVEL_CAR = 70, /**< Car or vacuum cleaner (1.0 attn) */
+ SNDLEVEL_NORMAL = 75, /**< Normal sound level */
+ SNDLEVEL_TRAFFIC = 75, /**< Busy traffic (0.8 attn) */
+ SNDLEVEL_MINIBIKE = 80, /**< Mini-bike, alarm clock (0.7 attn) */
+ SNDLEVEL_SCREAMING = 90, /**< Screaming child (0.5 attn) */
+ SNDLEVEL_TRAIN = 100, /**< Subway train, pneumatic drill (0.4 attn) */
+ SNDLEVEL_HELICOPTER = 105, /**< Helicopter */
+ SNDLEVEL_SNOWMOBILE = 110, /**< Snow mobile */
+ SNDLEVEL_AIRCRAFT = 120, /**< Auto horn, aircraft */
+ SNDLEVEL_RAIDSIREN = 130, /**< Air raid siren */
+ SNDLEVEL_GUNFIRE = 140, /**< Gunshot, jet engine (0.27 attn) */
+ SNDLEVEL_ROCKET = 180, /**< Rocket launching (0.2 attn) */
+};
+
+#define SNDVOL_NORMAL 1.0 /**< Normal volume */
+#define SNDPITCH_NORMAL 100 /**< Normal pitch */
+#define SNDPITCH_LOW 95 /**< A low pitch */
+#define SNDPITCH_HIGH 120 /**< A high pitch */
+#define SNDATTN_NONE 0.0 /**< No attenuation */
+#define SNDATTN_NORMAL 0.8 /**< Normal attenuation */
+#define SNDATTN_STATIC 1.25 /**< Static attenuation? */
+#define SNDATTN_RICOCHET 1.5 /**< Ricochet effect */
+#define SNDATTN_IDLE 2.0 /**< Idle attenuation? */
+
+/**
+ * Prefetches a sound.
+ *
+ * @param name Sound file name relative to the "sounds" folder.
+ * @noreturn
+ */
+native PrefetchSound(const String:name[]);
+
+/**
+ * This function is not known to work, and may crash. You should
+ * not use it. It is provided for backwards compatibility only.
+ *
+ * @param name Sound file name relative to the "sounds" folder.
+ * @return Duration in seconds.
+ */
+#pragma deprecated Does not work, may crash.
+native Float:GetSoundDuration(const String:name[]);
+
+/**
+ * Emits an ambient sound.
+ *
+ * @param name Sound file name relative to the "sounds" folder.
+ * @param pos Origin of sound.
+ * @param entity Entity index to associate sound with.
+ * @param level Sound level (from 0 to 255).
+ * @param flags Sound flags.
+ * @param vol Volume (from 0.0 to 1.0).
+ * @param pitch Pitch (from 0 to 255).
+ * @param delay Play delay.
+ * @noreturn
+ */
+native EmitAmbientSound(const String:name[],
+ const Float:pos[3],
+ entity = SOUND_FROM_WORLD,
+ level = SNDLEVEL_NORMAL,
+ flags = SND_NOFLAGS,
+ Float:vol = SNDVOL_NORMAL,
+ pitch = SNDPITCH_NORMAL,
+ Float:delay = 0.0);
+
+/**
+ * Fades a client's volume level toward silence or a given percentage.
+ *
+ * @param client Client index.
+ * @param percent Fade percentage.
+ * @param outtime Fade out time, in seconds.
+ * @param holdtime Hold time, in seconds.
+ * @param intime Fade in time, in seconds.
+ * @noreturn
+ * @error Invalid client index or client not in game.
+ */
+native FadeClientVolume(client, Float:percent, Float:outtime, Float:holdtime, Float:intime);
+
+/**
+ * Stops a sound.
+ *
+ * @param entity Entity index.
+ * @param channel Channel number.
+ * @param name Sound file name relative to the "sounds" folder.
+ * @noreturn
+ */
+native StopSound(entity, channel, const String:name[]);
+
+/**
+ * Emits a sound to a list of clients.
+ *
+ * @param clients Array of client indexes.
+ * @param numClients Number of clients in the array.
+ * @param sample Sound file name relative to the "sounds" folder.
+ * @param entity Entity to emit from.
+ * @param channel Channel to emit with.
+ * @param level Sound level.
+ * @param flags Sound flags.
+ * @param volume Sound volume.
+ * @param pitch Sound pitch.
+ * @param speakerentity Unknown.
+ * @param origin Sound origin.
+ * @param dir Sound direction.
+ * @param updatePos Unknown (updates positions?)
+ * @param soundtime Alternate time to play sound for.
+ * @param ... Optional list of Float[3] arrays to specify additional origins.
+ * @noreturn
+ * @error Invalid client index.
+ */
+native EmitSound(const clients[],
+ numClients,
+ const String:sample[],
+ entity = SOUND_FROM_PLAYER,
+ channel = SNDCHAN_AUTO,
+ level = SNDLEVEL_NORMAL,
+ flags = SND_NOFLAGS,
+ Float:volume = SNDVOL_NORMAL,
+ pitch = SNDPITCH_NORMAL,
+ speakerentity = -1,
+ const Float:origin[3] = NULL_VECTOR,
+ const Float:dir[3] = NULL_VECTOR,
+ bool:updatePos = true,
+ Float:soundtime = 0.0,
+ any:...);
+
+/**
+ * Emits a sentence to a list of clients.
+ *
+ * @param clients Array of client indexes.
+ * @param numClients Number of clients in the array.
+ * @param sentence Sentence index (from PrecacheSenteFile).
+ * @param entity Entity to emit from.
+ * @param channel Channel to emit with.
+ * @param level Sound level.
+ * @param flags Sound flags.
+ * @param volume Sound volume.
+ * @param pitch Sound pitch.
+ * @param speakerentity Unknown.
+ * @param origin Sound origin.
+ * @param dir Sound direction.
+ * @param updatePos Unknown (updates positions?)
+ * @param soundtime Alternate time to play sound for.
+ * @param ... Optional list of Float[3] arrays to specify additional origins.
+ * @noreturn
+ * @error Invalid client index.
+ */
+native EmitSentence(const clients[],
+ numClients,
+ sentence,
+ entity,
+ channel = SNDCHAN_AUTO,
+ level = SNDLEVEL_NORMAL,
+ flags = SND_NOFLAGS,
+ Float:volume = SNDVOL_NORMAL,
+ pitch = SNDPITCH_NORMAL,
+ speakerentity = -1,
+ const Float:origin[3] = NULL_VECTOR,
+ const Float:dir[3] = NULL_VECTOR,
+ bool:updatePos = true,
+ Float:soundtime = 0.0,
+ any:...);
+
+/**
+ *Calculates gain of sound on given distance with given sound level in decibel
+ *
+ * @param soundlevel decibel of sound, like SNDLEVEL_NORMAL or integer value
+ * @param distance distance of sound to calculate, not meter or feet, but Source Engine`s normal Coordinate unit
+ * @return gain of sound. you can multiply this with original sound`s volume to calculate volume on given distance
+ */
+native Float:GetDistGainFromSoundLevel(soundlevel, Float:distance);
+
+/**
+ * Called when an ambient sound is about to be emitted to one or more clients.
+ *
+ * NOTICE: all parameters can be overwritten to modify the default behavior.
+ *
+ * @param sample Sound file name relative to the "sounds" folder.
+ * @param entity Entity index associated to the sound.
+ * @param volume Volume (from 0.0 to 1.0).
+ * @param level Sound level (from 0 to 255).
+ * @param pitch Pitch (from 0 to 255).
+ * @param pos Origin of sound.
+ * @param flags Sound flags.
+ * @param delay Play delay.
+ * @return Plugin_Continue to allow the sound to be played, Plugin_Stop to block it,
+ * Plugin_Changed when any parameter has been modified.
+ */
+functag public Action:AmbientSHook(String:sample[PLATFORM_MAX_PATH], &entity, &Float:volume, &level, &pitch, Float:pos[3], &flags, &Float:delay);
+
+/**
+ * Called when a sound is going to be emitted to one or more clients.
+ * NOTICE: all params can be overwritten to modify the default behaviour.
+ *
+ * @param clients Array of client indexes.
+ * @param numClients Number of clients in the array (modify this value if you add/remove elements from the client array).
+ * @param sample Sound file name relative to the "sounds" folder.
+ * @param entity Entity emitting the sound.
+ * @param channel Channel emitting the sound.
+ * @param volume Sound volume.
+ * @param level Sound level.
+ * @param pitch Sound pitch.
+ * @param flags Sound flags.
+ * @return Plugin_Continue to allow the sound to be played, Plugin_Stop to block it,
+ * Plugin_Changed when any parameter has been modified.
+ */
+functag public Action:NormalSHook(clients[64], &numClients, String:sample[PLATFORM_MAX_PATH], &entity, &channel, &Float:volume, &level, &pitch, &flags);
+
+/**
+ * Hooks all played ambient sounds.
+ *
+ * @param hook Function to use as a hook.
+ * @noreturn
+ * @error Invalid function hook.
+ */
+native AddAmbientSoundHook(AmbientSHook:hook);
+
+/**
+ * Hooks all played normal sounds.
+ *
+ * @param hook Function to use as a hook.
+ * @noreturn
+ * @error Invalid function hook.
+ */
+native AddNormalSoundHook(NormalSHook:hook);
+
+/**
+ * Unhooks all played ambient sounds.
+ *
+ * @param hook Function used for the hook.
+ * @noreturn
+ * @error Invalid function hook.
+ */
+native RemoveAmbientSoundHook(AmbientSHook:hook);
+
+/**
+ * Unhooks all played normal sounds.
+ *
+ * @param hook Function used for the hook.
+ * @noreturn
+ * @error Invalid function hook.
+ */
+native RemoveNormalSoundHook(NormalSHook:hook);
+
+/**
+ * Wrapper to emit sound to one client.
+ *
+ * @param client Client index.
+ * @param sample Sound file name relative to the "sounds" folder.
+ * @param entity Entity to emit from.
+ * @param channel Channel to emit with.
+ * @param level Sound level.
+ * @param flags Sound flags.
+ * @param volume Sound volume.
+ * @param pitch Sound pitch.
+ * @param speakerentity Unknown.
+ * @param origin Sound origin.
+ * @param dir Sound direction.
+ * @param updatePos Unknown (updates positions?)
+ * @param soundtime Alternate time to play sound for.
+ * @noreturn
+ * @error Invalid client index.
+ */
+stock EmitSoundToClient(client,
+ const String:sample[],
+ entity = SOUND_FROM_PLAYER,
+ channel = SNDCHAN_AUTO,
+ level = SNDLEVEL_NORMAL,
+ flags = SND_NOFLAGS,
+ Float:volume = SNDVOL_NORMAL,
+ pitch = SNDPITCH_NORMAL,
+ speakerentity = -1,
+ const Float:origin[3] = NULL_VECTOR,
+ const Float:dir[3] = NULL_VECTOR,
+ bool:updatePos = true,
+ Float:soundtime = 0.0)
+{
+ new clients[1];
+ clients[0] = client;
+ /* Save some work for SDKTools and remove SOUND_FROM_PLAYER references */
+ entity = (entity == SOUND_FROM_PLAYER) ? client : entity;
+ EmitSound(clients, 1, sample, entity, channel,
+ level, flags, volume, pitch, speakerentity,
+ origin, dir, updatePos, soundtime);
+}
+
+/**
+ * Wrapper to emit sound to all clients.
+ *
+ * @param sample Sound file name relative to the "sounds" folder.
+ * @param entity Entity to emit from.
+ * @param channel Channel to emit with.
+ * @param level Sound level.
+ * @param flags Sound flags.
+ * @param volume Sound volume.
+ * @param pitch Sound pitch.
+ * @param speakerentity Unknown.
+ * @param origin Sound origin.
+ * @param dir Sound direction.
+ * @param updatePos Unknown (updates positions?)
+ * @param soundtime Alternate time to play sound for.
+ * @noreturn
+ * @error Invalid client index.
+ */
+stock EmitSoundToAll(const String:sample[],
+ entity = SOUND_FROM_PLAYER,
+ channel = SNDCHAN_AUTO,
+ level = SNDLEVEL_NORMAL,
+ flags = SND_NOFLAGS,
+ Float:volume = SNDVOL_NORMAL,
+ pitch = SNDPITCH_NORMAL,
+ speakerentity = -1,
+ const Float:origin[3] = NULL_VECTOR,
+ const Float:dir[3] = NULL_VECTOR,
+ bool:updatePos = true,
+ Float:soundtime = 0.0)
+{
+ new clients[MaxClients];
+ new total = 0;
+
+ for (new i=1; i<=MaxClients; i++)
+ {
+ if (IsClientInGame(i))
+ {
+ clients[total++] = i;
+ }
+ }
+
+ if (!total)
+ {
+ return;
+ }
+
+ EmitSound(clients, total, sample, entity, channel,
+ level, flags, volume, pitch, speakerentity,
+ origin, dir, updatePos, soundtime);
+}
+
+/**
+ * Converts an attenuation value to a sound level.
+ * This function is from the HL2SDK.
+ *
+ * @param attn Attenuation value.
+ * @return Integer sound level.
+ */
+stock ATTN_TO_SNDLEVEL(Float:attn)
+{
+ if (attn > 0.0)
+ {
+ return RoundFloat(50.0 + (20.0 / attn));
+ }
+ return 0;
+}
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_stocks.inc b/sourcemod-1.5-dev/scripting/include/sdktools_stocks.inc
new file mode 100644
index 0000000..744df58
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_stocks.inc
@@ -0,0 +1,76 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_stocks_included
+ #endinput
+#endif
+#define _sdktools_stocks_included
+
+/**
+ * Given a partial team name, attempts to find a matching team.
+ *
+ * The search is performed case insensitively and only against the
+ * first N characters of the team names, where N is the number of
+ * characters in the search pattern.
+ *
+ * @param name Partial or full team name.
+ * @return A valid team index on success.
+ * -1 if no team matched.
+ * -2 if more than one team matched.
+ */
+stock FindTeamByName(const String:name[])
+{
+ new name_len = strlen(name);
+ new num_teams = GetTeamCount();
+ decl String:team_name[32];
+ new found_team = -1;
+
+ for (new i = 0; i < num_teams; i++)
+ {
+ GetTeamName(i, team_name, sizeof(team_name));
+
+ if (strncmp(team_name, name, name_len, false) == 0)
+ {
+ if (found_team >= 0)
+ {
+ return -2;
+ }
+ else
+ {
+ found_team = i;
+ }
+ }
+ }
+
+ return found_team;
+}
+
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_stringtables.inc b/sourcemod-1.5-dev/scripting/include/sdktools_stringtables.inc
new file mode 100644
index 0000000..8c4ee08
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_stringtables.inc
@@ -0,0 +1,180 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_stringtables_included
+ #endinput
+#endif
+#define _sdktools_stringtables_included
+
+#define INVALID_STRING_TABLE -1 /**< An invalid string table index */
+#define INVALID_STRING_INDEX -1 /**< An invalid string index in a table */
+
+/**
+ * Searches for a string table.
+ *
+ * @param name Name of string table to find.
+ * @return A string table index number if found, INVALID_STRING_TABLE otherwise.
+ */
+native FindStringTable(const String:name[]);
+
+/**
+ * Returns the number of string tables that currently exist.
+ *
+ * @return Number of string tables that currently exist.
+ */
+native GetNumStringTables();
+
+/**
+ * Returns the number of strings that currently exist in a given string table.
+ *
+ * @param tableidx A string table index.
+ * @return Number of strings that currently exist.
+ * @error Invalid string table index.
+ */
+native GetStringTableNumStrings(tableidx);
+
+/**
+ * Returns the maximum number of strings that are allowed in a given string table.
+ *
+ * @param tableidx A string table index.
+ * @return Maximum number of strings allowed.
+ * @error Invalid string table index.
+ */
+native GetStringTableMaxStrings(tableidx);
+
+/**
+ * Retrieves the name of a string table.
+ *
+ * @param tableidx A string table index.
+ * @param name Buffer to store the name of the string table.
+ * @param maxlength Maximum length of string buffer.
+ * @return Number of bytes written to the buffer (UTF-8 safe).
+ * @error Invalid string table index.
+ */
+native GetStringTableName(tableidx, String:name[], maxlength);
+
+/**
+ * Searches for the index of a given string in a string table.
+ *
+ * @param tableidx A string table index.
+ * @param str String to find.
+ * @return String index if found, INVALID_STRING_INDEX otherwise.
+ * @error Invalid string table index.
+ */
+native FindStringIndex(tableidx, const String:str[]);
+
+/**
+ * Retrieves the string at a given index of a string table.
+ *
+ * @param tableidx A string table index.
+ * @param stringidx A string index.
+ * @param str Buffer to store the string value.
+ * @param maxlength Maximum length of string buffer.
+ * @return Number of bytes written to the buffer (UTF-8 safe).
+ * @error Invalid string table index or string index.
+ */
+native ReadStringTable(tableidx, stringidx, String:str[], maxlength);
+
+/**
+ * Returns the length of the user data associated with a given string index.
+ *
+ * @param tableidx A string table index.
+ * @param stringidx A string index.
+ * @return Length of user data. This will be 0 if there is no user data.
+ * @error Invalid string table index or string index.
+ */
+native GetStringTableDataLength(tableidx, stringidx);
+
+/**
+ * Retrieves the user data associated with a given string index.
+ *
+ * @param tableidx A string table index.
+ * @param stringidx A string index.
+ * @param userdata Buffer to store the user data. This will be set to "" if there is no user data.
+ * @param maxlength Maximum length of string buffer.
+ * @return Number of bytes written to the buffer (UTF-8 safe).
+ * @error Invalid string table index or string index.
+ */
+native GetStringTableData(tableidx, stringidx, String:userdata[], maxlength);
+
+/**
+ * Sets the user data associated with a given string index.
+ *
+ * @param tableidx A string table index.
+ * @param stringidx A string index.
+ * @param userdata User data string that will be set.
+ * @param length Length of user data string. This should include the null terminator.
+ * @return Number of bytes written to the buffer (UTF-8 safe).
+ * @error Invalid string table index or string index.
+ */
+native SetStringTableData(tableidx, stringidx, const String:userdata[], length);
+
+/**
+ * Adds a string to a given string table.
+ *
+ * @param tableidx A string table index.
+ * @param str String to add.
+ * @param userdata An optional user data string.
+ * @param length Length of user data string. This should include the null terminator.
+ * If set to -1, then user data will be not be altered if the specified string
+ * already exists in the string table.
+ */
+native AddToStringTable(tableidx, const String:str[], const String:userdata[]="", length=-1);
+
+/**
+ * Locks or unlocks the network string tables.
+ *
+ * @param lock Determines whether network string tables should be locked.
+ * True means the tables should be locked for writing; false means unlocked.
+ * @return Previous lock state.
+ */
+native bool:LockStringTables(bool:lock);
+
+/**
+ * Adds a file to the downloadables network string table.
+ * This forces a client to download the file if they do not already have it.
+ *
+ * @param filename File that will be added to downloadables table.
+ */
+stock AddFileToDownloadsTable(const String:filename[])
+{
+ static table = INVALID_STRING_TABLE;
+
+ if (table == INVALID_STRING_TABLE)
+ {
+ table = FindStringTable("downloadables");
+ }
+
+ new bool:save = LockStringTables(false);
+ AddToStringTable(table, filename);
+ LockStringTables(save);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_tempents.inc b/sourcemod-1.5-dev/scripting/include/sdktools_tempents.inc
new file mode 100644
index 0000000..9b980c2
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_tempents.inc
@@ -0,0 +1,228 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_tempents_included
+ #endinput
+#endif
+#define _sdktools_tempents_included
+
+/**
+ * Called when a temp entity is going to be sent.
+ *
+ * @param te_name TE name.
+ * @param Players Array containing target player indexes.
+ * @param numClients Number of players in the array.
+ * @param delay Delay in seconds to send the TE.
+ * @return Plugin_Continue to allow the transmission of the TE, Plugin_Stop to block it.
+ */
+functag public Action:TEHook(const String:te_name[], const Players[], numClients, Float:delay);
+
+/**
+ * Hooks a temp entity.
+ *
+ * @param te_name TE name to hook.
+ * @param hook Function to use as a hook.
+ * @noreturn
+ * @error Temp Entity name not available or invalid function hook.
+ */
+native AddTempEntHook(const String:te_name[], TEHook:hook);
+
+/**
+ * Removes a temp entity hook.
+ *
+ * @param te_name TE name to unhook.
+ * @param hook Function used for the hook.
+ * @noreturn
+ * @error Temp Entity name not available or invalid function hook.
+ */
+native RemoveTempEntHook(const String:te_name[], TEHook:hook);
+
+/**
+ * Starts a temp entity transmission.
+ *
+ * @param te_name TE name.
+ * @noreturn
+ * @error Temp Entity name not available.
+ */
+native TE_Start(const String:te_name[]);
+
+/**
+ * Checks if a certain TE property exists.
+ *
+ * @param prop Property to use.
+ * @return True if the property exists, otherwise false.
+ */
+native bool:TE_IsValidProp(const String:prop[]);
+
+/**
+ * Sets an integer value in the current temp entity.
+ *
+ * @param prop Property to use.
+ * @param value Integer value to set.
+ * @noreturn
+ * @error Property not found.
+ */
+native TE_WriteNum(const String:prop[], value);
+
+/**
+ * Reads an integer value in the current temp entity.
+ *
+ * @param prop Property to use.
+ * @return Property value.
+ * @error Property not found.
+ */
+native TE_ReadNum(const String:prop[]);
+
+/**
+ * Sets a floating point number in the current temp entity.
+ *
+ * @param prop Property to use.
+ * @param value Floating point number to set.
+ * @noreturn
+ * @error Property not found.
+ */
+native TE_WriteFloat(const String:prop[], Float:value);
+
+/**
+ * Reads a floating point number in the current temp entity.
+ *
+ * @param prop Property to use.
+ * @noreturn Property value.
+ * @error Property not found.
+ */
+native Float:TE_ReadFloat(const String:prop[]);
+
+/**
+ * Sets a vector in the current temp entity.
+ *
+ * @param prop Property to use.
+ * @param vector Vector to set.
+ * @noreturn
+ * @error Property not found.
+ */
+native TE_WriteVector(const String:prop[], const Float:vector[3]);
+
+/**
+ * Reads a vector in the current temp entity.
+ *
+ * @param prop Property to use.
+ * @param vector Vector to read.
+ * @noreturn
+ * @error Property not found.
+ */
+native TE_ReadVector(const String:prop[], Float:vector[3]);
+
+/**
+ * Sets a QAngle in the current temp entity.
+ *
+ * @param prop Property to use.
+ * @param angles Angles to set.
+ * @return True on success, otherwise false.
+ * @error Property not found.
+ */
+native TE_WriteAngles(const String:prop[], const Float:angles[3]);
+
+/**
+ * Sets an array of floats in the current temp entity.
+ *
+ * @param prop Property to use.
+ * @param array Array of values to copy.
+ * @param arraySize Number of values to copy.
+ * @return True on success, otherwise false.
+ * @error Property not found.
+ */
+native TE_WriteFloatArray(const String:prop[], const Float:array[], arraySize);
+
+/**
+ * Sends the current temp entity to one or more clients.
+ *
+ * @param clients Array containing player indexes to broadcast to.
+ * @param numClients Number of players in the array.
+ * @param delay Delay in seconds to send the TE.
+ * @noreturn
+ * @error Invalid client index or client not in game.
+ */
+native TE_Send(clients[], numClients, Float:delay=0.0);
+
+/**
+ * Sets an encoded entity index in the current temp entity.
+ * (This is usually used for m_nStartEntity and m_nEndEntity).
+ *
+ * @param prop Property to use.
+ * @param value Value to set.
+ * @noreturn
+ * @error Property not found.
+ */
+stock TE_WriteEncodedEnt(const String:prop[], value)
+{
+ new encvalue = (value & 0x0FFF) | ((1 & 0xF)<<12);
+ return TE_WriteNum(prop, encvalue);
+}
+
+/**
+ * Broadcasts the current temp entity to all clients.
+ * @note See TE_Start().
+ *
+ * @param delay Delay in seconds to send the TE.
+ * @noreturn
+ */
+stock TE_SendToAll(Float:delay=0.0)
+{
+ new total = 0;
+ new clients[MaxClients];
+ for (new i=1; i<=MaxClients; i++)
+ {
+ if (IsClientInGame(i))
+ {
+ clients[total++] = i;
+ }
+ }
+ return TE_Send(clients, total, delay);
+}
+
+/**
+ * Sends the current TE to only a client.
+ * @note See TE_Start().
+ *
+ * @param client Client to send to.
+ * @param delay Delay in seconds to send the TE.
+ * @noreturn
+ * @error Invalid client index or client not in game.
+ */
+stock TE_SendToClient(client, Float:delay=0.0)
+{
+ new players[1];
+
+ players[0] = client;
+
+ return TE_Send(players, 1, delay);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_tempents_stocks.inc b/sourcemod-1.5-dev/scripting/include/sdktools_tempents_stocks.inc
new file mode 100644
index 0000000..6a632c0
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_tempents_stocks.inc
@@ -0,0 +1,458 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _te_stocks_included
+ #endinput
+#endif
+#define _te_stocks_included
+
+/**
+ * @section TE Explosion flags.
+ */
+#define TE_EXPLFLAG_NONE 0x0 /**< all flags clear makes default Half-Life explosion */
+#define TE_EXPLFLAG_NOADDITIVE 0x1 /**< sprite will be drawn opaque (ensure that the sprite you send is a non-additive sprite) */
+#define TE_EXPLFLAG_NODLIGHTS 0x2 /**< do not render dynamic lights */
+#define TE_EXPLFLAG_NOSOUND 0x4 /**< do not play client explosion sound */
+#define TE_EXPLFLAG_NOPARTICLES 0x8 /**< do not draw particles */
+#define TE_EXPLFLAG_DRAWALPHA 0x10 /**< sprite will be drawn alpha */
+#define TE_EXPLFLAG_ROTATE 0x20 /**< rotate the sprite randomly */
+#define TE_EXPLFLAG_NOFIREBALL 0x40 /**< do not draw a fireball */
+#define TE_EXPLFLAG_NOFIREBALLSMOKE 0x80 /**< do not draw smoke with the fireball */
+
+/**
+ * @endsection
+ */
+
+/**
+ * @section TE Beam flags.
+ */
+#define FBEAM_STARTENTITY 0x00000001
+#define FBEAM_ENDENTITY 0x00000002
+#define FBEAM_FADEIN 0x00000004
+#define FBEAM_FADEOUT 0x00000008
+#define FBEAM_SINENOISE 0x00000010
+#define FBEAM_SOLID 0x00000020
+#define FBEAM_SHADEIN 0x00000040
+#define FBEAM_SHADEOUT 0x00000080
+#define FBEAM_ONLYNOISEONCE 0x00000100 /**< Only calculate our noise once */
+#define FBEAM_NOTILE 0x00000200
+#define FBEAM_USE_HITBOXES 0x00000400 /**< Attachment indices represent hitbox indices instead when this is set. */
+#define FBEAM_STARTVISIBLE 0x00000800 /**< Has this client actually seen this beam's start entity yet? */
+#define FBEAM_ENDVISIBLE 0x00001000 /**< Has this client actually seen this beam's end entity yet? */
+#define FBEAM_ISACTIVE 0x00002000
+#define FBEAM_FOREVER 0x00004000
+#define FBEAM_HALOBEAM 0x00008000 /**< When drawing a beam with a halo, don't ignore the segments and endwidth */
+
+/**
+ * @endsection
+ */
+
+/**
+ * Sets up a sparks effect.
+ *
+ * @param pos Position of the sparks.
+ * @param dir Direction of the sparks.
+ * @param Magnitude Sparks size.
+ * @param TrailLength Trail lenght of the sparks.
+ * @noreturn
+ */
+stock TE_SetupSparks(const Float:pos[3], const Float:dir[3], Magnitude, TrailLength)
+{
+ TE_Start("Sparks");
+ TE_WriteVector("m_vecOrigin[0]", pos);
+ TE_WriteVector("m_vecDir", dir);
+ TE_WriteNum("m_nMagnitude", Magnitude);
+ TE_WriteNum("m_nTrailLength", TrailLength);
+}
+
+/**
+ * Sets up a smoke effect.
+ *
+ * @param pos Position of the smoke.
+ * @param Model Precached model index.
+ * @param Scale Scale of the smoke.
+ * @param FrameRate Frame rate of the smoke.
+ * @noreturn
+ */
+stock TE_SetupSmoke(const Float:pos[3], Model, Float:Scale, FrameRate)
+{
+ TE_Start("Smoke");
+ TE_WriteVector("m_vecOrigin", pos);
+ TE_WriteNum("m_nModelIndex", Model);
+ TE_WriteFloat("m_fScale", Scale);
+ TE_WriteNum("m_nFrameRate", FrameRate);
+}
+
+/**
+ * Sets up a dust cloud effect.
+ *
+ * @param pos Position of the dust.
+ * @param dir Direction of the dust.
+ * @param Size Dust cloud size.
+ * @param Speed Dust cloud speed.
+ * @noreturn
+ */
+stock TE_SetupDust(const Float:pos[3], const Float:dir[3], Float:Size, Float:Speed)
+{
+ TE_Start("Dust");
+ TE_WriteVector("m_vecOrigin[0]", pos);
+ TE_WriteVector("m_vecDirection", dir);
+ TE_WriteFloat("m_flSize", Size);
+ TE_WriteFloat("m_flSpeed", Speed);
+}
+
+/**
+ * Sets up a muzzle flash effect.
+ *
+ * @param pos Position of the muzzle flash.
+ * @param angles Rotation angles of the muzzle flash.
+ * @param Scale Scale of the muzzle flash.
+ * @param Type Muzzle flash type to render (Mod specific).
+ * @noreturn
+ */
+stock TE_SetupMuzzleFlash(const Float:pos[3], const Float:angles[3], Float:Scale, Type)
+{
+ TE_Start("MuzzleFlash");
+ TE_WriteVector("m_vecOrigin", pos);
+ TE_WriteVector("m_vecAngles", angles);
+ TE_WriteFloat("m_flScale", Scale);
+ TE_WriteNum("m_nType", Type);
+}
+
+/**
+ * Sets up a metal sparks effect.
+ *
+ * @param pos Position of the metal sparks.
+ * @param dir Direction of the metal sparks.
+ * @noreturn
+ */
+stock TE_SetupMetalSparks(const Float:pos[3], const Float:dir[3])
+{
+ TE_Start("Metal Sparks");
+ TE_WriteVector("m_vecPos", pos);
+ TE_WriteVector("m_vecDir", dir);
+}
+
+/**
+ * Sets up an energy splash effect.
+ *
+ * @param pos Position of the energy splash.
+ * @param dir Direction of the energy splash.
+ * @param Explosive Makes the effect explosive.
+ * @noreturn
+ */
+stock TE_SetupEnergySplash(const Float:pos[3], const Float:dir[3], bool:Explosive)
+{
+ TE_Start("Energy Splash");
+ TE_WriteVector("m_vecPos", pos);
+ TE_WriteVector("m_vecDir", dir);
+ TE_WriteNum("m_bExplosive", Explosive);
+}
+
+/**
+ * Sets up an armor ricochet effect.
+ *
+ * @param pos Position of the armor ricochet.
+ * @param dir Directon of the armor ricochet.
+ * @noreturn
+ */
+stock TE_SetupArmorRicochet(const Float:pos[3], const Float:dir[3])
+{
+ TE_Start("Armor Ricochet");
+ TE_WriteVector("m_vecPos", pos);
+ TE_WriteVector("m_vecDir", dir);
+}
+
+/**
+ * Sets up a glowing sprite effect.
+ *
+ * @param pos Position of the sprite.
+ * @param Model Precached model index.
+ * @param Life Time duration of the sprite.
+ * @param Size Sprite size.
+ * @param Brightness Sprite brightness.
+ * @noreturn
+ */
+stock TE_SetupGlowSprite(const Float:pos[3], Model, Float:Life, Float:Size, Brightness)
+{
+ TE_Start("GlowSprite");
+ TE_WriteVector("m_vecOrigin", pos);
+ TE_WriteNum("m_nModelIndex", Model);
+ TE_WriteFloat("m_fScale", Size);
+ TE_WriteFloat("m_fLife", Life);
+ TE_WriteNum("m_nBrightness", Brightness);
+}
+
+/**
+ * Sets up a explosion effect.
+ *
+ * @param pos Explosion position.
+ * @param Model Precached model index.
+ * @param Scale Explosion scale.
+ * @param Framerate Explosion frame rate.
+ * @param Flags Explosion flags.
+ * @param Radius Explosion radius.
+ * @param Magnitude Explosion size.
+ * @param normal Normal vector to the explosion.
+ * @param MaterialType Exploded material type.
+ * @noreturn
+ */
+stock TE_SetupExplosion(const Float:pos[3], Model, Float:Scale, Framerate, Flags, Radius, Magnitude, const Float:normal[3]={0.0, 0.0, 1.0}, MaterialType='C')
+{
+ TE_Start("Explosion");
+ TE_WriteVector("m_vecOrigin[0]", pos);
+ TE_WriteVector("m_vecNormal", normal);
+ TE_WriteNum("m_nModelIndex", Model);
+ TE_WriteFloat("m_fScale", Scale);
+ TE_WriteNum("m_nFrameRate", Framerate);
+ TE_WriteNum("m_nFlags", Flags);
+ TE_WriteNum("m_nRadius", Radius);
+ TE_WriteNum("m_nMagnitude", Magnitude);
+ TE_WriteNum("m_chMaterialType", MaterialType);
+}
+
+/**
+ * Sets up a blood sprite effect.
+ *
+ * @param pos Position of the sprite.
+ * @param dir Sprite direction.
+ * @param color Color array (r, g, b, a).
+ * @param Size Sprite size.
+ * @param SprayModel Precached model index.
+ * @param BloodDropModel Precached model index.
+ * @noreturn
+ */
+stock TE_SetupBloodSprite(const Float:pos[3], const Float:dir[3], const color[4], Size, SprayModel, BloodDropModel)
+{
+ TE_Start("Blood Sprite");
+ TE_WriteVector("m_vecOrigin", pos);
+ TE_WriteVector("m_vecDirection", dir);
+ TE_WriteNum("r", color[0]);
+ TE_WriteNum("g", color[1]);
+ TE_WriteNum("b", color[2]);
+ TE_WriteNum("a", color[3]);
+ TE_WriteNum("m_nSize", Size);
+ TE_WriteNum("m_nSprayModel", SprayModel);
+ TE_WriteNum("m_nDropModel", BloodDropModel);
+}
+
+/**
+ * Sets up a beam ring point effect.
+ *
+ * @param center Center position of the ring.
+ * @param Start_Radius Initial ring radius.
+ * @param End_Radius Final ring radius.
+ * @param ModelIndex Precached model index.
+ * @param HaloIndex Precached model index.
+ * @param StartFrame Initital frame to render.
+ * @param FrameRate Ring frame rate.
+ * @param Life Time duration of the ring.
+ * @param Width Beam width.
+ * @param Amplitude Beam amplitude.
+ * @param Color Color array (r, g, b, a).
+ * @param Speed Speed of the beam.
+ * @param Flags Beam flags.
+ * @noreturn
+ */
+stock TE_SetupBeamRingPoint(const Float:center[3], Float:Start_Radius, Float:End_Radius, ModelIndex, HaloIndex, StartFrame,
+ FrameRate, Float:Life, Float:Width, Float:Amplitude, const Color[4], Speed, Flags)
+{
+ TE_Start("BeamRingPoint");
+ TE_WriteVector("m_vecCenter", center);
+ TE_WriteFloat("m_flStartRadius", Start_Radius);
+ TE_WriteFloat("m_flEndRadius", End_Radius);
+ TE_WriteNum("m_nModelIndex", ModelIndex);
+ TE_WriteNum("m_nHaloIndex", HaloIndex);
+ TE_WriteNum("m_nStartFrame", StartFrame);
+ TE_WriteNum("m_nFrameRate", FrameRate);
+ TE_WriteFloat("m_fLife", Life);
+ TE_WriteFloat("m_fWidth", Width);
+ TE_WriteFloat("m_fEndWidth", Width);
+ TE_WriteFloat("m_fAmplitude", Amplitude);
+ TE_WriteNum("r", Color[0]);
+ TE_WriteNum("g", Color[1]);
+ TE_WriteNum("b", Color[2]);
+ TE_WriteNum("a", Color[3]);
+ TE_WriteNum("m_nSpeed", Speed);
+ TE_WriteNum("m_nFlags", Flags);
+ TE_WriteNum("m_nFadeLength", 0);
+}
+
+/**
+ * Sets up a point to point beam effect.
+ *
+ * @param start Start position of the beam.
+ * @param end End position of the beam.
+ * @param ModelIndex Precached model index.
+ * @param HaloIndex Precached model index.
+ * @param StartFrame Initital frame to render.
+ * @param FrameRate Beam frame rate.
+ * @param Life Time duration of the beam.
+ * @param Width Initial beam width.
+ * @param EndWidth Final beam width.
+ * @param FadeLength Beam fade time duration.
+ * @param Amplitude Beam amplitude.
+ * @param Color Color array (r, g, b, a).
+ * @param Speed Speed of the beam.
+ * @noreturn
+ */
+stock TE_SetupBeamPoints(const Float:start[3], const Float:end[3], ModelIndex, HaloIndex, StartFrame, FrameRate, Float:Life,
+ Float:Width, Float:EndWidth, FadeLength, Float:Amplitude, const Color[4], Speed)
+{
+ TE_Start("BeamPoints");
+ TE_WriteVector("m_vecStartPoint", start);
+ TE_WriteVector("m_vecEndPoint", end);
+ TE_WriteNum("m_nModelIndex", ModelIndex);
+ TE_WriteNum("m_nHaloIndex", HaloIndex);
+ TE_WriteNum("m_nStartFrame", StartFrame);
+ TE_WriteNum("m_nFrameRate", FrameRate);
+ TE_WriteFloat("m_fLife", Life);
+ TE_WriteFloat("m_fWidth", Width);
+ TE_WriteFloat("m_fEndWidth", EndWidth);
+ TE_WriteFloat("m_fAmplitude", Amplitude);
+ TE_WriteNum("r", Color[0]);
+ TE_WriteNum("g", Color[1]);
+ TE_WriteNum("b", Color[2]);
+ TE_WriteNum("a", Color[3]);
+ TE_WriteNum("m_nSpeed", Speed);
+ TE_WriteNum("m_nFadeLength", FadeLength);
+}
+
+/**
+ * Sets up an entity to entity laser effect.
+ *
+ * @param StartEntity Entity index from where the beam starts.
+ * @param EndEntity Entity index from where the beam ends.
+ * @param ModelIndex Precached model index.
+ * @param HaloIndex Precached model index.
+ * @param StartFrame Initital frame to render.
+ * @param FrameRate Beam frame rate.
+ * @param Life Time duration of the beam.
+ * @param Width Initial beam width.
+ * @param EndWidth Final beam width.
+ * @param FadeLength Beam fade time duration.
+ * @param Amplitude Beam amplitude.
+ * @param Color Color array (r, g, b, a).
+ * @param Speed Speed of the beam.
+ * @noreturn
+ */
+stock TE_SetupBeamLaser(StartEntity, EndEntity, ModelIndex, HaloIndex, StartFrame, FrameRate, Float:Life,
+ Float:Width, Float:EndWidth, FadeLength, Float:Amplitude, const Color[4], Speed)
+{
+ TE_Start("BeamLaser");
+ TE_WriteEncodedEnt("m_nStartEntity", StartEntity);
+ TE_WriteEncodedEnt("m_nEndEntity", EndEntity);
+ TE_WriteNum("m_nModelIndex", ModelIndex);
+ TE_WriteNum("m_nHaloIndex", HaloIndex);
+ TE_WriteNum("m_nStartFrame", StartFrame);
+ TE_WriteNum("m_nFrameRate", FrameRate);
+ TE_WriteFloat("m_fLife", Life);
+ TE_WriteFloat("m_fWidth", Width);
+ TE_WriteFloat("m_fEndWidth", EndWidth);
+ TE_WriteFloat("m_fAmplitude", Amplitude);
+ TE_WriteNum("r", Color[0]);
+ TE_WriteNum("g", Color[1]);
+ TE_WriteNum("b", Color[2]);
+ TE_WriteNum("a", Color[3]);
+ TE_WriteNum("m_nSpeed", Speed);
+ TE_WriteNum("m_nFadeLength", FadeLength);
+}
+
+/**
+ * Sets up a beam ring effect.
+ *
+ * @param StartEntity Entity index from where the ring starts.
+ * @param EndEntity Entity index from where the ring ends.
+ * @param ModelIndex Precached model index.
+ * @param HaloIndex Precached model index.
+ * @param StartFrame Initital frame to render.
+ * @param FrameRate Ring frame rate.
+ * @param Life Time duration of the ring.
+ * @param Width Beam width.
+ * @param Amplitude Beam amplitude.
+ * @param Color Color array (r, g, b, a).
+ * @param Speed Speed of the beam.
+ * @param Flags Beam flags.
+ * @noreturn
+ */
+stock TE_SetupBeamRing(StartEntity, EndEntity, ModelIndex, HaloIndex, StartFrame, FrameRate, Float:Life, Float:Width, Float:Amplitude, const Color[4], Speed, Flags)
+{
+ TE_Start("BeamRing");
+ TE_WriteEncodedEnt("m_nStartEntity", StartEntity);
+ TE_WriteEncodedEnt("m_nEndEntity", EndEntity);
+ TE_WriteNum("m_nModelIndex", ModelIndex);
+ TE_WriteNum("m_nHaloIndex", HaloIndex);
+ TE_WriteNum("m_nStartFrame", StartFrame);
+ TE_WriteNum("m_nFrameRate", FrameRate);
+ TE_WriteFloat("m_fLife", Life);
+ TE_WriteFloat("m_fWidth", Width);
+ TE_WriteFloat("m_fEndWidth", Width);
+ TE_WriteFloat("m_fAmplitude", Amplitude);
+ TE_WriteNum("r", Color[0]);
+ TE_WriteNum("g", Color[1]);
+ TE_WriteNum("b", Color[2]);
+ TE_WriteNum("a", Color[3]);
+ TE_WriteNum("m_nSpeed", Speed);
+ TE_WriteNum("m_nFadeLength", 0);
+ TE_WriteNum("m_nFlags", Flags);
+}
+
+/**
+ * Sets up a follow beam effect.
+ *
+ * @param EntIndex Entity index from where the beam starts.
+ * @param ModelIndex Precached model index.
+ * @param HaloIndex Precached model index.
+ * @param Life Time duration of the beam.
+ * @param Width Initial beam width.
+ * @param EndWidth Final beam width.
+ * @param FadeLength Beam fade time duration.
+ * @param Color Color array (r, g, b, a).
+ * @noreturn
+ */
+stock TE_SetupBeamFollow(EntIndex, ModelIndex, HaloIndex, Float:Life, Float:Width, Float:EndWidth, FadeLength, const Color[4])
+{
+ TE_Start("BeamFollow");
+ TE_WriteEncodedEnt("m_iEntIndex", EntIndex);
+ TE_WriteNum("m_nModelIndex", ModelIndex);
+ TE_WriteNum("m_nHaloIndex", HaloIndex);
+ TE_WriteNum("m_nStartFrame", 0);
+ TE_WriteNum("m_nFrameRate", 0);
+ TE_WriteFloat("m_fLife", Life);
+ TE_WriteFloat("m_fWidth", Width);
+ TE_WriteFloat("m_fEndWidth", EndWidth);
+ TE_WriteNum("m_nFadeLength", FadeLength);
+ TE_WriteNum("r", Color[0]);
+ TE_WriteNum("g", Color[1]);
+ TE_WriteNum("b", Color[2]);
+ TE_WriteNum("a", Color[3]);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_trace.inc b/sourcemod-1.5-dev/scripting/include/sdktools_trace.inc
new file mode 100644
index 0000000..845a566
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_trace.inc
@@ -0,0 +1,374 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_trace_included
+ #endinput
+#endif
+#define _sdktools_trace_included
+
+#define CONTENTS_EMPTY 0 /**< No contents. */
+#define CONTENTS_SOLID 0x1 /**< an eye is never valid in a solid . */
+#define CONTENTS_WINDOW 0x2 /**< translucent, but not watery (glass). */
+#define CONTENTS_AUX 0x4
+#define CONTENTS_GRATE 0x8 /**< alpha-tested "grate" textures. Bullets/sight pass through, but solids don't. */
+#define CONTENTS_SLIME 0x10
+#define CONTENTS_WATER 0x20
+#define CONTENTS_MIST 0x40
+#define CONTENTS_OPAQUE 0x80 /**< things that cannot be seen through (may be non-solid though). */
+#define LAST_VISIBLE_CONTENTS 0x80
+#define ALL_VISIBLE_CONTENTS (LAST_VISIBLE_CONTENTS | (LAST_VISIBLE_CONTENTS-1))
+#define CONTENTS_TESTFOGVOLUME 0x100
+#define CONTENTS_UNUSED5 0x200
+#define CONTENTS_UNUSED6 0x4000
+#define CONTENTS_TEAM1 0x800 /**< per team contents used to differentiate collisions. */
+#define CONTENTS_TEAM2 0x1000 /**< between players and objects on different teams. */
+#define CONTENTS_IGNORE_NODRAW_OPAQUE 0x2000 /**< ignore CONTENTS_OPAQUE on surfaces that have SURF_NODRAW. */
+#define CONTENTS_MOVEABLE 0x4000 /**< hits entities which are MOVETYPE_PUSH (doors, plats, etc) */
+#define CONTENTS_AREAPORTAL 0x8000 /**< remaining contents are non-visible, and don't eat brushes. */
+#define CONTENTS_PLAYERCLIP 0x10000
+#define CONTENTS_MONSTERCLIP 0x20000
+
+/**
+ * @section currents can be added to any other contents, and may be mixed
+ */
+#define CONTENTS_CURRENT_0 0x40000
+#define CONTENTS_CURRENT_90 0x80000
+#define CONTENTS_CURRENT_180 0x100000
+#define CONTENTS_CURRENT_270 0x200000
+#define CONTENTS_CURRENT_UP 0x400000
+#define CONTENTS_CURRENT_DOWN 0x800000
+
+/**
+ * @endsection
+ */
+
+#define CONTENTS_ORIGIN 0x1000000 /**< removed before bsping an entity. */
+#define CONTENTS_MONSTER 0x2000000 /**< should never be on a brush, only in game. */
+#define CONTENTS_DEBRIS 0x4000000
+#define CONTENTS_DETAIL 0x8000000 /**< brushes to be added after vis leafs. */
+#define CONTENTS_TRANSLUCENT 0x10000000 /**< auto set if any surface has trans. */
+#define CONTENTS_LADDER 0x20000000
+#define CONTENTS_HITBOX 0x40000000 /**< use accurate hitboxes on trace. */
+
+/**
+ * @section Trace masks.
+ */
+#define MASK_ALL (0xFFFFFFFF)
+#define MASK_SOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE) /**< everything that is normally solid */
+#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE) /**< everything that blocks player movement */
+#define MASK_NPCSOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE) /**< blocks npc movement */
+#define MASK_WATER (CONTENTS_WATER|CONTENTS_MOVEABLE|CONTENTS_SLIME) /**< water physics in these contents */
+#define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_OPAQUE) /**< everything that blocks line of sight for AI, lighting, etc */
+#define MASK_OPAQUE_AND_NPCS (MASK_OPAQUE|CONTENTS_MONSTER) /**< everything that blocks line of sight for AI, lighting, etc, but with monsters added. */
+#define MASK_VISIBLE (MASK_OPAQUE|CONTENTS_IGNORE_NODRAW_OPAQUE) /**< everything that blocks line of sight for players */
+#define MASK_VISIBLE_AND_NPCS (MASK_OPAQUE_AND_NPCS|CONTENTS_IGNORE_NODRAW_OPAQUE) /**< everything that blocks line of sight for players, but with monsters added. */
+#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_HITBOX) /**< bullets see these as solid */
+#define MASK_SHOT_HULL (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_GRATE) /**< non-raycasted weapons see this as solid (includes grates) */
+#define MASK_SHOT_PORTAL (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW) /**< hits solids (not grates) and passes through everything else */
+#define MASK_SOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_GRATE) /**< everything normally solid, except monsters (world+brush only) */
+#define MASK_PLAYERSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_PLAYERCLIP|CONTENTS_GRATE) /**< everything normally solid for player movement, except monsters (world+brush only) */
+#define MASK_NPCSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE) /**< everything normally solid for npc movement, except monsters (world+brush only) */
+#define MASK_NPCWORLDSTATIC (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE) /**< just the world, used for route rebuilding */
+#define MASK_SPLITAREAPORTAL (CONTENTS_WATER|CONTENTS_SLIME) /**< These are things that can split areaportals */
+
+/**
+ * @endsection
+ */
+
+enum RayType
+{
+ RayType_EndPoint, /**< The trace ray will go from the start position to the end position. */
+ RayType_Infinite /**< The trace ray will go from the start position to infinity using a direction vector. */
+};
+
+funcenum TraceEntityFilter
+{
+ /**
+ * Called on entity filtering.
+ *
+ * @param entity Entity index.
+ * @param contentsMask Contents Mask.
+ * @return True to allow the current entity to be hit, otherwise false.
+ */
+ bool:public(entity, contentsMask),
+
+ /**
+ * Called on entity filtering.
+ *
+ * @param entity Entity index.
+ * @param contentsMask Contents Mask.
+ * @param data Data value, if used.
+ * @return True to allow the current entity to be hit, otherwise false.
+ */
+ bool:public(entity, contentsMask, any:data),
+};
+
+/**
+ * Get the contents mask and the entity index at the given position.
+ *
+ * @param pos World position to test.
+ * @param entindex Entity index found at the given position (by reference).
+ * @return Contents mask.
+ */
+native TR_GetPointContents(const Float:pos[3], &entindex=-1);
+
+/**
+ * Get the point contents testing only the given entity index.
+ *
+ * @param entindex Entity index to test.
+ * @param pos World position.
+ * @return Contents mask.
+ */
+native TR_GetPointContentsEnt(entindex, const Float:pos[3]);
+
+/**
+ * Starts up a new trace ray using a global trace result.
+ *
+ * @param pos Starting position of the ray.
+ * @param vec Depending on RayType, it will be used as the
+ * ending point, or the direction angle.
+ * @param flags Trace flags.
+ * @param rtype Method to calculate the ray direction.
+ * @noreturn
+ */
+native TR_TraceRay(const Float:pos[3],
+ const Float:vec[3],
+ flags,
+ RayType:rtype);
+
+/**
+ * Starts up a new trace hull using a global trace result.
+ *
+ * @param pos Starting position of the ray.
+ * @param vec Ending position of the ray.
+ * @param mins Hull minimum size.
+ * @param maxs Hull maximum size.
+ * @param flags Trace flags.
+ * @noreturn
+ */
+native TR_TraceHull(const Float:pos[3],
+ const Float:vec[3],
+ const Float:mins[3],
+ const Float:maxs[3],
+ flags);
+
+/**
+ * Starts up a new trace ray using a global trace result and a customized
+ * trace ray filter.
+ *
+ * Calling TR_Trace*Filter or TR_Trace*FilterEx from inside a filter
+ * function is currently not allowed and may not work.
+ *
+ * @param pos Starting position of the ray.
+ * @param vec Depending on RayType, it will be used as the ending
+ * point, or the direction angle.
+ * @param flags Trace flags.
+ * @param rtype Method to calculate the ray direction.
+ * @param filter Function to use as a filter.
+ * @param data Arbitrary data value to pass through to the filter
+ * function.
+ * @noreturn
+ */
+native TR_TraceRayFilter(const Float:pos[3],
+ const Float:vec[3],
+ flags,
+ RayType:rtype,
+ TraceEntityFilter:filter,
+ any:data=0);
+
+/**
+ * Starts up a new trace hull using a global trace result and a customized
+ * trace ray filter.
+ *
+ * Calling TR_Trace*Filter or TR_Trace*FilterEx from inside a filter
+ * function is currently not allowed and may not work.
+ *
+ * @param pos Starting position of the ray.
+ * @param vec Depending on RayType, it will be used as the ending
+ * point, or the direction angle.
+ * @param mins Hull minimum size.
+ * @param maxs Hull maximum size.
+ * @param flags Trace flags.
+ * @param filter Function to use as a filter.
+ * @param data Arbitrary data value to pass through to the filter
+ * function.
+ * @noreturn
+ */
+native TR_TraceHullFilter(const Float:pos[3],
+ const Float:vec[3],
+ const Float:mins[3],
+ const Float:maxs[3],
+ flags,
+ TraceEntityFilter:filter,
+ any:data=0);
+
+/**
+ * Starts up a new trace ray using a new trace result.
+ *
+ * @param pos Starting position of the ray.
+ * @param vec Depending on RayType, it will be used as the ending
+ * point, or the direction angle.
+ * @param flags Trace flags.
+ * @param rtype Method to calculate the ray direction.
+ * @return Ray trace handle, which must be closed via CloseHandle().
+ */
+native Handle:TR_TraceRayEx(const Float:pos[3],
+ const Float:vec[3],
+ flags,
+ RayType:rtype);
+
+/**
+ * Starts up a new trace hull using a new trace result.
+ *
+ * @param pos Starting position of the ray.
+ * @param vec Ending position of the ray.
+ * @param mins Hull minimum size.
+ * @param maxs Hull maximum size.
+ * @param flags Trace flags.
+ * @return Ray trace handle, which must be closed via CloseHandle().
+ */
+native Handle:TR_TraceHullEx(const Float:pos[3],
+ const Float:vec[3],
+ const Float:mins[3],
+ const Float:maxs[3],
+ flags);
+
+/**
+ * Starts up a new trace ray using a new trace result and a customized
+ * trace ray filter.
+ *
+ * Calling TR_Trace*Filter or TR_TraceRay*Ex from inside a filter
+ * function is currently not allowed and may not work.
+ *
+ * @param pos Starting position of the ray.
+ * @param vec Depending on RayType, it will be used as the ending
+ * point, or the direction angle.
+ * @param flags Trace flags.
+ * @param rtype Method to calculate the ray direction.
+ * @param filter Function to use as a filter.
+ * @param data Arbitrary data value to pass through to the filter function.
+ * @return Ray trace handle, which must be closed via CloseHandle().
+ */
+native Handle:TR_TraceRayFilterEx(const Float:pos[3],
+ const Float:vec[3],
+ flags,
+ RayType:rtype,
+ TraceEntityFilter:filter,
+ any:data=0);
+
+/**
+ * Starts up a new trace hull using a new trace result and a customized
+ * trace ray filter.
+ *
+ * Calling TR_Trace*Filter or TR_Trace*FilterEx from inside a filter
+ * function is currently not allowed and may not work.
+ *
+ * @param pos Starting position of the ray.
+ * @param vec Ending position of the ray.
+ * @param mins Hull minimum size.
+ * @param maxs Hull maximum size.
+ * @param flags Trace flags.
+ * @param filter Function to use as a filter.
+ * @param data Arbitrary data value to pass through to the filter function.
+ * @return Ray trace handle, which must be closed via CloseHandle().
+ */
+native Handle:TR_TraceHullFilterEx(const Float:pos[3],
+ const Float:vec[3],
+ const Float:mins[3],
+ const Float:maxs[3],
+ flags,
+ TraceEntityFilter:filter,
+ any:data=0);
+
+/**
+ * Returns the time fraction from a trace result (1.0 means no collision).
+ *
+ * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result.
+ * @return Time fraction value of the trace.
+ * @error Invalid Handle.
+ */
+native Float:TR_GetFraction(Handle:hndl=INVALID_HANDLE);
+
+/**
+ * Returns the collision position of a trace result.
+ *
+ * @param pos Vector buffer to store data in.
+ * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native TR_GetEndPosition(Float:pos[3], Handle:hndl=INVALID_HANDLE);
+
+/**
+ * Returns the entity index that collided with the trace.
+ *
+ * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result.
+ * @return Entity index or -1 for no collision.
+ * @error Invalid Handle.
+ */
+native TR_GetEntityIndex(Handle:hndl=INVALID_HANDLE);
+
+/**
+ * Returns if there was any kind of collision along the trace ray.
+ *
+ * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result.
+ * @return True if any collision found, otherwise false.
+ * @error Invalid Handle.
+ */
+native bool:TR_DidHit(Handle:hndl=INVALID_HANDLE);
+
+/**
+ * Returns in which body hit group the trace collided if any.
+ *
+ * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result.
+ * @return Body hit group.
+ * @error Invalid Handle.
+ */
+native TR_GetHitGroup(Handle:hndl=INVALID_HANDLE);
+
+/**
+ * Find the normal vector to the collison plane of a trace.
+ *
+ * @param hndl A trace Handle, or INVALID_HANDLE to use a global trace result.
+ * @param normal Vector buffer to store the vector normal to the collision plane
+ * @noreturn
+ * @error Invalid Handle
+ */
+native TR_GetPlaneNormal(Handle:hndl, Float:normal[3]);
+
+/**
+ * Tests a point to see if it's outside any playable area
+ *
+ * @param pos Vector buffer to store data in.
+ * @return True if outside world, otherwise false.
+ */
+native TR_PointOutsideWorld(Float:pos[3]); \ No newline at end of file
diff --git a/sourcemod-1.5-dev/scripting/include/sdktools_voice.inc b/sourcemod-1.5-dev/scripting/include/sdktools_voice.inc
new file mode 100644
index 0000000..132898b
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sdktools_voice.inc
@@ -0,0 +1,124 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sdktools_voice_included
+ #endinput
+#endif
+#define _sdktools_voice_included
+
+/**
+ * @section voice flags.
+ */
+#define VOICE_NORMAL 0 /**< Allow the client to listen and speak normally. */
+#define VOICE_MUTED 1 /**< Mutes the client from speaking to everyone. */
+#define VOICE_SPEAKALL 2 /**< Allow the client to speak to everyone. */
+#define VOICE_LISTENALL 4 /**< Allow the client to listen to everyone. */
+#define VOICE_TEAM 8 /**< Allow the client to always speak to team, even when dead. */
+#define VOICE_LISTENTEAM 16 /**< Allow the client to always hear teammates, including dead ones. */
+
+/**
+ * @endsection
+ */
+
+enum ListenOverride
+{
+ Listen_Default = 0, /**< Leave it up to the game */
+ Listen_No, /**< Can't hear */
+ Listen_Yes, /**< Can hear */
+};
+
+/**
+ * Set the client listening flags.
+ *
+ * @param client The client index
+ * @param flags The voice flags
+ * @noreturn
+ */
+native SetClientListeningFlags(client, flags);
+
+/**
+ * Retrieve the client current listening flags.
+ *
+ * @param client The client index
+ * @return The current voice flags
+ */
+native GetClientListeningFlags(client);
+
+/**
+ * Set the receiver ability to listen to the sender.
+ *
+ * @param iReceiver The listener index.
+ * @param iSender The sender index.
+ * @param bListen True if the receiver can listen to the sender, false otherwise.
+ * @return True if successful otherwise false.
+ */
+#pragma deprecated Use SetListenOverride() instead
+native bool:SetClientListening(iReceiver, iSender, bool:bListen);
+
+/**
+ * Retrieves if the receiver can listen to the sender.
+ *
+ * @param iReceiver The listener index.
+ * @param iSender The sender index.
+ * @return True if successful otherwise false.
+ */
+#pragma deprecated GetListenOverride() instead
+native bool:GetClientListening(iReceiver, iSender);
+
+/**
+ * Override the receiver's ability to listen to the sender.
+ *
+ * @param iReceiver The listener index.
+ * @param iSender The sender index.
+ * @param override The override of the receiver's ability to listen to the sender.
+ * @return True if successful otherwise false.
+ */
+native bool:SetListenOverride(iReceiver, iSender, ListenOverride:override);
+
+/**
+ * Retrieves the override of the receiver's ability to listen to the sender.
+ *
+ * @param iReceiver The listener index.
+ * @param iSender The sender index.
+ * @return The override value.
+ */
+native ListenOverride:GetListenOverride(iReceiver, iSender);
+
+/**
+ * Retrieves if the muter has muted the mutee.
+ *
+ * @param iMuter The muter index.
+ * @param iMutee The mutee index.
+ * @return True if muter has muted mutee, false otherwise.
+ */
+native bool:IsClientMuted(iMuter, iMutee);
+
diff --git a/sourcemod-1.5-dev/scripting/include/smlib.inc b/sourcemod-1.5-dev/scripting/include/smlib.inc
new file mode 100644
index 0000000..2d6413a
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib.inc
@@ -0,0 +1,32 @@
+#if defined _smlib_included
+ #endinput
+#endif
+#define _smlib_included
+
+#define SMLIB_VERSION "0.9.7"
+
+#include <smlib/general>
+
+#include <smlib/arrays>
+#include <smlib/clients>
+#include <smlib/colors>
+#include <smlib/concommands>
+#include <smlib/convars>
+#include <smlib/crypt>
+#include <smlib/debug>
+#include <smlib/dynarrays>
+#include <smlib/edicts>
+#include <smlib/effects>
+#include <smlib/entities>
+#include <smlib/files>
+#include <smlib/game>
+#include <smlib/math>
+#include <smlib/menus>
+//#include <smlib/pluginmanager>
+#include <smlib/server>
+#include <smlib/strings>
+#include <smlib/sql>
+#include <smlib/teams>
+#include <smlib/vehicles>
+#include <smlib/weapons>
+#include <smlib/world>
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/arrays.inc b/sourcemod-1.5-dev/scripting/include/smlib/arrays.inc
new file mode 100644
index 0000000..8faaa4e
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/arrays.inc
@@ -0,0 +1,158 @@
+#if defined _smlib_array_included
+ #endinput
+#endif
+#define _smlib_array_included
+
+#include <sourcemod>
+
+/**
+ * Returns the index for the first occurance of the given value.
+ * If the value cannot be found, -1 will be returned.
+ *
+ * @param array Static Array.
+ * @param size Size of the Array.
+ * @param value Value to search for.
+ * @param start Optional: Offset where to start (0 - (size-1)).
+ * @return Array index, or -1 if the value couldn't be found.
+ */
+stock Array_FindValue(any:array[], size, any:value, start=0)
+{
+ if (start < 0) {
+ start = 0;
+ }
+
+ for (new i=start; i < size; i++) {
+
+ if (array[i] == value) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * Searchs for the first occurance of a string in the array.
+ * If the value cannot be located, -1 will be returned.
+ *
+ * @param array Static Array.
+ * @param size Size of the Array.
+ * @param value String to search for.
+ * @param start Optional: Offset where to start(0 - (size-1)).
+ * @return Array index, or -1 if the value couldn't be found.
+ */
+stock Array_FindString(const String:array[][], size, const String:str[], bool:caseSensitive=true, start=0)
+{
+ if (start < 0) {
+ start = 0;
+ }
+
+ for (new i=start; i < size; i++) {
+
+ if (StrEqual(array[i], str, caseSensitive)) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * Returns the Index of the Lowest value in the array
+ *
+ * @param array Static Array.
+ * @param size Size of the Array.
+ * @param start Optional: Offset where to start (0 - (size-1)).
+ * @return Array index.
+ */
+stock Array_FindLowestValue(any:array[], size, start=0)
+{
+ if (start < 0) {
+ start = 0;
+ }
+
+ new any:value = array[start];
+ new any:tempValue;
+ new x = start;
+
+ for (new i=start; i < size; i++) {
+
+ tempValue = array[i];
+
+ if (tempValue < value) {
+ value = tempValue;
+ x = i;
+ }
+
+ }
+
+ return x;
+}
+
+/**
+ * Returns the Index of the Highest value in the array
+ *
+ * @param array Static Array.
+ * @param size Size of the Array.
+ * @param start Optional: Offset where to start (0 - (size-1)).
+ * @return Array index.
+ */
+stock Array_FindHighestValue(any:array[], size, start=0)
+{
+ if (start < 0) {
+ start = 0;
+ }
+
+ new any:value = array[start];
+ new any:tempValue;
+ new x = start;
+
+ for (new i=start; i < size; i++) {
+
+ tempValue = array[i];
+
+ if (tempValue > value) {
+ value = tempValue;
+ x = i;
+ }
+
+ }
+
+ return x;
+}
+
+/**
+ * Fills an array with a given value in a 1 dimensional static array.
+ * You can specify the amount of cells to be written.
+ *
+ * @param array Static Array.
+ * @param size Number of cells to write (eg. the array's size)
+ * @param value Fill value.
+ * @param start Optional: Offset where to start (0 - (size-1)).
+ * @noreturn
+ */
+stock Array_Fill(any:array[], size, any:value, start=0)
+{
+ if (start < 0) {
+ start = 0;
+ }
+
+ for (new i=start; i < size; i++) {
+ array[i] = value;
+ }
+}
+
+/**
+ * Copies a 1 dimensional static array.
+ *
+ * @param array Static Array to copy from.
+ * @param newArray New Array to copy to.
+ * @param size Size of the array (or number of cells to copy)
+ * @noreturn
+ */
+stock Array_Copy(const any:array[], any:newArray[], size)
+{
+ for (new i=0; i < size; i++) {
+ newArray[i] = array[i];
+ }
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/clients.inc b/sourcemod-1.5-dev/scripting/include/smlib/clients.inc
new file mode 100644
index 0000000..a3afd78
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/clients.inc
@@ -0,0 +1,3121 @@
+#if defined _smlib_client_included
+ #endinput
+#endif
+#define _smlib_client_included
+
+// Defined here beacause needed in teams.inc
+#define CLIENTFILTER_ALL 0 // No filtering
+#define CLIENTFILTER_BOTS ( 1 << 1 ) // Fake clients
+#define CLIENTFILTER_NOBOTS ( 1 << 2 ) // No fake clients
+#define CLIENTFILTER_AUTHORIZED ( 1 << 3 ) // SteamID validated
+#define CLIENTFILTER_NOTAUTHORIZED ( 1 << 4 ) // SteamID not validated (yet)
+#define CLIENTFILTER_ADMINS ( 1 << 5 ) // Generic Admins (or higher)
+#define CLIENTFILTER_NOADMINS ( 1 << 6 ) // No generic admins
+// All flags below require ingame checking (optimization)
+#define CLIENTFILTER_INGAME ( 1 << 7 ) // Ingame
+#define CLIENTFILTER_INGAMEAUTH ( 1 << 8 ) // Ingame & Authorized
+#define CLIENTFILTER_NOTINGAME ( 1 << 9 ) // Not ingame (currently connecting)
+#define CLIENTFILTER_ALIVE ( 1 << 10 ) // Alive
+#define CLIENTFILTER_DEAD ( 1 << 11 ) // Dead
+#define CLIENTFILTER_SPECTATORS ( 1 << 12 ) // Spectators
+#define CLIENTFILTER_NOSPECTATORS ( 1 << 13 ) // No Spectators
+#define CLIENTFILTER_OBSERVERS ( 1 << 14 ) // Observers
+#define CLIENTFILTER_NOOBSERVERS ( 1 << 15 ) // No Observers
+#define CLIENTFILTER_TEAMONE ( 1 << 16 ) // First Team (Terrorists, ...)
+#define CLIENTFILTER_TEAMTWO ( 1 << 17 ) // Second Team (Counter-Terrorists, ...)
+
+#include <sourcemod>
+#include <entity_prop_stocks>
+#include <sdktools_engine>
+#include <sdktools_trace>
+#include <sdktools_voice>
+#include <smlib/general>
+#include <smlib/colors>
+#include <smlib/edicts>
+#include <smlib/math>
+#include <smlib/teams>
+#include <smlib/weapons>
+
+/**
+ * Very useful macro to iterate all clients
+ * matching the specified flags.
+ *
+ * @param 1 Name of the client index variable (will be only valid in the loop).
+ * @param 2 CLIENTFILTER_ flags to check.
+ */
+#define LOOP_CLIENTS(%1,%2) for (new %1=Client_GetNext(%2); %1 >= 1 && %1 <= MaxClients; %1=Client_GetNext(%2, ++%1))
+
+/**
+ * Macro for iterating trough all observers of a player.
+ *
+ * @param 1 Client Index for who to get the observers.
+ * @param 2 Name of the observer client index variable (will be only valid in the loop).
+ * @param 3 CLIENTFILTER_ flags to check.
+ */
+#define LOOP_OBSERVERS(%1,%2,%3) for (new %2=Client_GetNextObserver(%1, 1, %3); %2 >= 1 && %2 <= MaxClients; %2=Client_GetNextObserver(%1, ++%2, %3))
+
+/**
+ * Very useful macro to iterate all weapons of a client.
+ *
+ * @param 1 Client Index
+ * @param 2 Name of the weapon index variable (will be only valid in the loop).
+ * @param 3 Name of the client's weapon index variable (will be only valid in the loop).
+ */
+#define LOOP_CLIENTWEAPONS(%1,%2,%3) for (new %3, %2=Client_GetNextWeapon(%1, %3); %2 != -1; %2=Client_GetNextWeapon(%1, %3))
+
+// Hud Element hiding flags (possibly outdated)
+#define HIDEHUD_WEAPONSELECTION ( 1<<0 ) // Hide ammo count & weapon selection
+#define HIDEHUD_FLASHLIGHT ( 1<<1 )
+#define HIDEHUD_ALL ( 1<<2 )
+#define HIDEHUD_HEALTH ( 1<<3 ) // Hide health & armor / suit battery
+#define HIDEHUD_PLAYERDEAD ( 1<<4 ) // Hide when local player's dead
+#define HIDEHUD_NEEDSUIT ( 1<<5 ) // Hide when the local player doesn't have the HEV suit
+#define HIDEHUD_MISCSTATUS ( 1<<6 ) // Hide miscellaneous status elements (trains, pickup history, death notices, etc)
+#define HIDEHUD_CHAT ( 1<<7 ) // Hide all communication elements (saytext, voice icon, etc)
+#define HIDEHUD_CROSSHAIR ( 1<<8 ) // Hide crosshairs
+#define HIDEHUD_VEHICLE_CROSSHAIR ( 1<<9 ) // Hide vehicle crosshair
+#define HIDEHUD_INVEHICLE ( 1<<10 )
+#define HIDEHUD_BONUS_PROGRESS ( 1<<11 ) // Hide bonus progress display (for bonus map challenges)
+
+/**
+* Sets the Hide-Hud flags of a client
+*
+* @param client Client index.
+* @param flags Flag to set, use one of the HIDEHUD_ hiding constants
+* @noreturn
+*/
+stock Client_SetHideHud(client, flags)
+{
+ SetEntProp(client, Prop_Send, "m_iHideHUD", flags);
+}
+
+/**
+* Checks if the specified index is a player and connected.
+*
+* @param entity An entity index.
+* @param checkConnected Set to false to skip the IsClientConnected check
+* @return Returns true if the specified entity index is a player connected, false otherwise.
+*/
+stock bool:Client_IsValid(client, bool:checkConnected=true)
+{
+ if (client > 4096) {
+ client = EntRefToEntIndex(client);
+ }
+
+ if (client < 1 || client > MaxClients) {
+ return false;
+ }
+
+ if (checkConnected && !IsClientConnected(client)) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+* Checks if the specified index is a player and ingame.
+*
+* @param entity An entity index.
+* @return Returns true if the specified index is a player and ingame, false otherwise.
+*/
+stock bool:Client_IsIngame(client)
+{
+ if (!Client_IsValid(client, false)) {
+ return false;
+ }
+
+ return IsClientInGame(client);
+}
+
+/**
+* Checks if the specified index is a player, ingame and authorized.
+*
+* @param entity An entity index.
+* @return Returns true if the specified index is a player, ingame and authed, false otherwise.
+*/
+stock bool:Client_IsIngameAuthorized(client)
+{
+ if (!Client_IsIngame(client)) {
+ return false;
+ }
+
+ return IsClientAuthorized(client);
+}
+
+#define MAX_STEAMAUTH_LENGTH 21
+
+/**
+* Finds a player by his SteamID
+*
+* @param auth SteamID to search for
+* @return Client Index or -1
+*/
+stock Client_FindBySteamId(const String:auth[])
+{
+ new String:clientAuth[MAX_STEAMAUTH_LENGTH];
+ for (new client=1; client <= MaxClients; client++) {
+ if (!IsClientAuthorized(client)) {
+ continue;
+ }
+
+ GetClientAuthString(client, clientAuth, sizeof(clientAuth));
+
+ if (StrEqual(auth, clientAuth)) {
+ return client;
+ }
+ }
+
+ return -1;
+}
+
+/**
+* Finds a player by his name.
+* Only returns the first matching player.
+*
+* @param name Name to search for.
+* @param partOfName Whether to search for the part of a name or compare the full name.
+* @param caseSensitive If true, comparison is case sensitive. If false (default), comparison is case insensitive.
+* @return Client Index or -1
+*/
+stock Client_FindByName(const String:name[], bool:partOfName=true, bool:caseSensitive=false)
+{
+ new String:clientName[MAX_NAME_LENGTH];
+ for (new client=1; client <= MaxClients; client++) {
+ if (!IsClientAuthorized(client)) {
+ continue;
+ }
+
+ GetClientName(client, clientName, sizeof(clientName));
+
+ if (partOfName) {
+ if (StrContains(clientName, name, caseSensitive) != -1) {
+ return client;
+ }
+ }
+ else if (StrEqual(name, clientName, caseSensitive)) {
+ return client;
+ }
+ }
+
+ return -1;
+}
+
+// Spectator Movement modes
+enum Obs_Mode
+{
+ OBS_MODE_NONE = 0, // not in spectator mode
+ OBS_MODE_DEATHCAM, // special mode for death cam animation
+ OBS_MODE_FREEZECAM, // zooms to a target, and freeze-frames on them
+ OBS_MODE_FIXED, // view from a fixed camera position
+ OBS_MODE_IN_EYE, // follow a player in first person view
+ OBS_MODE_CHASE, // follow a player in third person view
+ OBS_MODE_ROAMING, // free roaming
+
+ NUM_OBSERVER_MODES
+};
+
+// Force Camera Restrictions with mp_forcecamera
+enum Obs_Allow
+{
+ OBS_ALLOW_ALL = 0, // allow all modes, all targets
+ OBS_ALLOW_TEAM, // allow only own team & first person, no PIP
+ OBS_ALLOW_NONE, // don't allow any spectating after death (fixed & fade to black)
+
+ OBS_ALLOW_NUM_MODES,
+};
+
+/**
+ * Gets the client's observer mode (Obs_Mode).
+ *
+ * @param client Client Index.
+ * @return The current observer mode (ObsMode).
+ */
+stock Obs_Mode:Client_GetObserverMode(client)
+{
+ return Obs_Mode:GetEntProp(client, Prop_Send, "m_iObserverMode");
+}
+
+
+/**
+ * Sets the client's observer mode.
+ * Use a value of the Obs_Mode enum.
+ * This is a rewrite of CBasePlayer::SetObserverMode().
+ *
+ * @param client Client Index.
+ * @param mode New Observer mode value (Obs_Mode).
+ * @param updateMoveType Set to true (default) to allow this function updating the movetype, false otherwise.
+ * @noreturn
+ */
+stock bool:Client_SetObserverMode(client, Obs_Mode:mode, bool:updateMoveType=true)
+{
+ if (mode < OBS_MODE_NONE || mode >= NUM_OBSERVER_MODES) {
+ return false;
+ }
+
+ // check mp_forcecamera settings for dead players
+ if (mode > OBS_MODE_FIXED && GetClientTeam(client) > TEAM_SPECTATOR)
+ {
+ new Handle:mp_forcecamera = FindConVar("mp_forcecamera");
+
+ if (mp_forcecamera != INVALID_HANDLE) {
+ switch (GetConVarInt(mp_forcecamera))
+ {
+ case OBS_ALLOW_TEAM: {
+ mode = OBS_MODE_IN_EYE;
+ }
+ case OBS_ALLOW_NONE: {
+ mode = OBS_MODE_FIXED; // don't allow anything
+ }
+ }
+ }
+ }
+
+ new Obs_Mode:observerMode = Client_GetObserverMode(client);
+ if (observerMode > OBS_MODE_DEATHCAM) {
+ // remember mode if we were really spectating before
+ Client_SetObserverLastMode(client, observerMode);
+ }
+
+ SetEntProp(client, Prop_Send, "m_iObserverMode", _:mode);
+
+ switch (mode) {
+ case OBS_MODE_NONE, OBS_MODE_FIXED, OBS_MODE_DEATHCAM: {
+ Client_SetFOV(client, 0); // Reset FOV
+
+ if (updateMoveType) {
+ SetEntityMoveType(client, MOVETYPE_NONE);
+ }
+ }
+ case OBS_MODE_CHASE, OBS_MODE_IN_EYE: {
+ // udpate FOV and viewmodels
+ Client_SetViewOffset(client, NULL_VECTOR);
+
+ if (updateMoveType) {
+ SetEntityMoveType(client, MOVETYPE_OBSERVER);
+ }
+ }
+ case OBS_MODE_ROAMING: {
+ Client_SetFOV(client, 0); // Reset FOV
+ Client_SetViewOffset(client, NULL_VECTOR);
+
+ if (updateMoveType) {
+ SetEntityMoveType(client, MOVETYPE_OBSERVER);
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Gets the client's last oberserver mode
+ *
+ * @param client Client Index.
+ * @return Last Observer mode
+ */
+stock Obs_Mode:Client_GetObserverLastMode(client)
+{
+ return Obs_Mode:GetEntProp(client, Prop_Data, "m_iObserverLastMode");
+}
+
+/**
+ * Sets the client's last oberserver mode
+ *
+ * @param client Client Index.
+ * @param mode Last Observer mode
+ * @noreturn
+ */
+stock Client_SetObserverLastMode(client, Obs_Mode:mode)
+{
+ SetEntProp(client, Prop_Data, "m_iObserverLastMode", _:mode);
+}
+
+/**
+ * Gets the client's view offset.
+ * This is the position relative to the client itself.
+ *
+ * @param client Client Index.
+ * @param vec Vector Buffer.
+ * @noreturn
+ */
+stock Client_GetViewOffset(client, Float:vec[3])
+{
+ GetEntPropVector(client, Prop_Data, "m_vecViewOffset", vec);
+}
+
+/**
+ * Sets the client's view offset.
+ * This is the position relative to the client itself.
+ *
+ * @param client Client Index.
+ * @param vec Vector buffer.
+ * @noreturn
+ */
+stock Client_SetViewOffset(client, Float:vec[3])
+{
+ SetEntPropVector(client, Prop_Data, "m_vecViewOffset", vec);
+}
+
+/**
+ * Gets the client's current observer target entity.
+ *
+ * @param client Client Index.
+ * @return Observed Entity Index.
+ */
+stock Client_GetObserverTarget(client)
+{
+ return GetEntPropEnt(client, Prop_Send, "m_hObserverTarget");
+}
+
+/**
+ * Sets the client's current observer target entity.
+ *
+ * @param client Client Index.
+ * @param entity Observed Entity Index.
+ * @param resetFOV If to reset the client's field of view.
+ * @noreturn
+ */
+stock Client_SetObserverTarget(client, entity, bool:resetFOV=true)
+{
+ SetEntPropEnt(client, Prop_Send, "m_hObserverTarget", entity);
+
+ if (resetFOV) {
+ Client_SetFOV(client, 0);
+ }
+}
+
+/**
+ * Gets the client's Field Of View.
+ *
+ * @param client Client Index.
+ * @return Field Of View
+ */
+stock Client_GetFOV(client)
+{
+ return GetEntProp(client, Prop_Send, "m_iFOV");
+}
+
+/**
+ * Sets the client's Field Of View.
+ *
+ * @param client Client Index.
+ * @param value Field Of View
+ * @noreturn
+ */
+stock Client_SetFOV(client, value)
+{
+ SetEntProp(client, Prop_Send, "m_iFOV", value);
+}
+
+/**
+ * Checks if the client's View Model is drawn for the client.
+ *
+ * @param client Client Index.
+ * @return True if the viewmodel is drawn, false otherwise.
+ */
+stock bool:Client_DrawViewModel(client)
+{
+ return bool:GetEntProp(client, Prop_Send, "m_bDrawViewmodel");
+}
+
+/**
+ * Sets if to draw the client's view model for the client.
+ *
+ * @param client Client Index.
+ * @param drawViewModel Set to true if to draw, false otherwise.
+ * @noreturn
+ */
+stock Client_SetDrawViewModel(client, bool:drawViewModel)
+{
+ SetEntProp(client, Prop_Send, "m_bDrawViewmodel", drawViewModel);
+}
+
+/**
+ * Puts the specified client into thirdperson or back to firstperson when false
+ * This doesn't work correctly in all games, it works in CS:S and DOD:S and some other games.
+ * Todo: Enhance this
+ *
+ * @param client Client Index.
+ * @param enable If set to true, the client will be put into thirdperson mode,
+ * if false the client will be put in firstperson mode.
+ * @noreturn
+ */
+stock Client_SetThirdPersonMode(client, enable=true)
+{
+ if (enable) {
+ Client_SetObserverTarget(client, 0);
+ Client_SetObserverMode(client, OBS_MODE_DEATHCAM, false);
+ Client_SetDrawViewModel(client, false);
+ Client_SetFOV(client, 120);
+ }
+ else {
+ Client_SetObserverTarget(client, -1);
+ Client_SetObserverMode(client, OBS_MODE_NONE, false);
+ Client_SetDrawViewModel(client, true);
+ Client_SetFOV(client, 90);
+ }
+}
+
+/**
+ * Checks if the client is in thirdperson mode
+ *
+ * @param client Cient Undex
+ * @return true if the client is currently in thirdperson mode, false otherwise
+ */
+stock Client_IsInThirdPersonMode(client)
+{
+ return GetEntProp(client, Prop_Data, "m_iObserverMode");
+}
+
+#define FFADE_IN 0x0001 // Just here so we don't pass 0 into the function
+#define FFADE_OUT 0x0002 // Fade out (not in)
+#define FFADE_MODULATE 0x0004 // Modulate (don't blend)
+#define FFADE_STAYOUT 0x0008 // ignores the duration, stays faded out until new ScreenFade message received
+#define FFADE_PURGE 0x0010 // Purges all other fades, replacing them with this one
+
+/**
+ * Fades a client's screen to a specified color
+ * Your adviced to read the FFADE_ Comments
+ *
+ * @param client Player for which to fade the screen
+ * @param duration duration in seconds the effect stays
+ * @param mode fade mode, see FFADE_ defines
+ * @param holdtime holdtime in seconds
+ * @param r red amount
+ * @param g green amount
+ * @param b blue amount
+ * @param a transparency
+ * @return True on success, false otherwise
+ */
+stock bool:Client_ScreenFade(client, duration, mode, holdtime=-1, r=0, g=0, b=0, a=255, bool:reliable=true)
+{
+ new Handle:userMessage = StartMessageOne("Fade", client, (reliable?USERMSG_RELIABLE:0));
+
+ if (userMessage == INVALID_HANDLE) {
+ return false;
+ }
+
+ if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available &&
+ GetUserMessageType() == UM_Protobuf) {
+
+ new color[4];
+ color[0] = r;
+ color[1] = g;
+ color[2] = b;
+ color[3] = a;
+
+ PbSetInt(userMessage, "duration", duration);
+ PbSetInt(userMessage, "hold_time", holdtime);
+ PbSetInt(userMessage, "flags", mode);
+ PbSetColor(userMessage, "clr", color);
+ }
+ else {
+ BfWriteShort(userMessage, duration); // Fade duration
+ BfWriteShort(userMessage, holdtime); // Fade hold time
+ BfWriteShort(userMessage, mode); // What to do
+ BfWriteByte(userMessage, r); // Color R
+ BfWriteByte(userMessage, g); // Color G
+ BfWriteByte(userMessage, b); // Color B
+ BfWriteByte(userMessage, a); // Color Alpha
+ }
+ EndMessage();
+
+ return true;
+}
+
+/**
+ * This function retrieves an array that holds all clones of a client by IP check.
+ * Size of CloneList has to be MaxClients at least, or MAX_PLAYERS
+ *
+ * @param client Client index.
+ * @param closelist An array that holds all clones of a client.
+ * @return Returns how many clones a client has.
+ */
+stock Client_GetClones(client, cloneList[])
+{
+ new x=0;
+ decl String:ip_client[16], String:ip_player[16];
+
+ GetClientIP(client, ip_client, sizeof(client));
+
+ for (new player=1; player <= MaxClients; player++) {
+
+ if (IsClientInGame(player)) {
+ GetClientIP(player, ip_player, sizeof(ip_player));
+
+ if (StrEqual(ip_client, ip_player, false)) {
+ cloneList[x++] = player;
+ }
+ }
+ }
+
+ return x;
+}
+
+/*
+ * This function returns true if the client is at a ladder..
+ *
+ * @param client Client index.
+ * @return Returns true if the client is on a ladder other wise false.
+ */
+stock bool:Client_IsOnLadder(client)
+{
+ new MoveType:movetype = GetEntityMoveType(client);
+
+ if (movetype == MOVETYPE_LADDER) {
+ return true;
+ }
+ else{
+ return false;
+ }
+}
+
+enum Water_level
+{
+ WATER_LEVEL_NOT_IN_WATER = 0,
+ WATER_LEVEL_FEET_IN_WATER,
+ WATER_LEVEL_WAIST_IN_WATER,
+ WATER_LEVEL_HEAD_IN_WATER
+};
+
+/*
+ * This function returns how deep a client is in water.
+ *
+ * @param client Client index.
+ * @return Returns 0 if not in water. 1 if feets are in water. 2 if waist is in water. 3 if head is in water.
+ */
+stock Water_Level:Client_GetWaterLevel(client)
+{
+ return Water_Level:GetEntProp(client, Prop_Send, "m_nWaterLevel");
+}
+
+/*
+ * Returns how much suit sprint power a client has left in percent.
+ *
+ * @param client Client index.
+ * @return returns the actual power left in percent.
+ */
+stock Float:Client_GetSuitSprintPower(client)
+{
+ return GetEntPropFloat(client, Prop_Send, "m_flSuitPower");
+}
+
+/*
+ * Sets a client suit sprint power in percent.
+ *
+ * @param client Client index.
+ * @param power power (0.0 to 100.0)
+ * @noreturn
+ */
+stock Client_SetSuitSprintPower(client, Float:power)
+{
+ SetEntPropFloat(client, Prop_Send, "m_flSuitPower", power);
+}
+
+/*
+ * Returns the client count put in the server.
+ *
+ * @param inGameOnly If false connecting players are also counted.
+ * @param countBots If true bots will be counted too.
+ * @return Client count in the server.
+ */
+stock Client_GetCount(bool:countInGameOnly=true, bool:countFakeClients=true)
+{
+ new numClients = 0;
+
+ for (new client=1; client <= MaxClients; client++) {
+
+ if (!IsClientConnected(client)) {
+ continue;
+ }
+
+ if (countInGameOnly && !IsClientInGame(client)) {
+ continue;
+ }
+
+ if (!countFakeClients && IsFakeClient(client)) {
+ continue;
+ }
+
+ numClients++;
+ }
+
+ return numClients;
+}
+
+/*
+ * Returns the ping of a client like it is displayed in the scoreboard.
+ * The weird calculation formula is taken from Valve's SDK
+ * hl2sdk\game\server\util.cpp: UTIL_GetPlayerConnectionInfo()
+ * The Scoreboard uses the goldSource corrected Ping, the net_graph doesn't
+ * For Fake Clients 0 is returned.
+ *
+ * @param client Client index
+ * @param goldSource If true, get the ping as displayed in the player's scoreboard, false returns the net_graph variant.
+ * @return Client's fake ping or 0 for fake clients
+ */
+stock Client_GetFakePing(client, bool:goldSource=true)
+{
+ if (IsFakeClient(client)) {
+ return 0;
+ }
+
+ new ping;
+ new Float:latency = GetClientLatency(client, NetFlow_Outgoing); // in seconds
+
+ // that should be the correct latency, we assume that cmdrate is higher
+ // then updaterate, what is the case for default settings
+ decl String:cl_cmdrate[4];
+ GetClientInfo(client, "cl_cmdrate", cl_cmdrate, sizeof(cl_cmdrate));
+
+ new Float:tickRate = GetTickInterval();
+ latency -= (0.5 / StringToInt(cl_cmdrate)) + TICKS_TO_TIME(1.0); // correct latency
+
+ if (goldSource) {
+ // in GoldSrc we had a different, not fixed tickrate. so we have to adjust
+ // Source pings by half a tick to match the old GoldSrc pings.
+ latency -= tickRate * 0.5;
+ }
+
+ ping = RoundFloat(latency * 1000.0); // as msecs
+ ping = Math_Clamp(ping, 5, 1000); // set bounds, dont show pings under 5 msecs
+
+ return ping;
+}
+
+/**
+ * Searches for the closest client in relation to the given client.
+ *
+ * @param client Client index
+ * @return The closest client or -1
+ */
+stock Client_GetClosestToClient(client)
+{
+ return Edict_GetClosestToEdict(client, true);
+}
+
+/**
+ * Gets the name of the last place (if set by the game)
+ *
+ * @param entity Entity index.
+ * @param buffer String buffer
+ * @param size Size of the String buffer
+ * @noreturn
+ */
+stock Client_GetLastPlaceName(client, String:buffer[], size)
+{
+ GetEntPropString(client, Prop_Send, "m_szLastPlaceName", buffer, size);
+}
+
+/**
+ * Returns the client's Score.
+ *
+ * @param client Client's index.
+ * @return Score.
+ */
+stock Client_GetScore(client)
+{
+ return GetClientFrags(client);
+}
+
+/**
+ * Sets the client's Score.
+ *
+ * @param client Client's index.
+ * @param value Score.
+ * @noreturn
+ */
+stock Client_SetScore(client, value)
+{
+ SetEntProp(client, Prop_Data, "m_iFrags", value);
+}
+
+/**
+ * Returns the client's Death count
+ *
+ * @param client Client's index.
+ * @return Death count
+ */
+stock Client_GetDeaths(client)
+{
+ return GetEntProp(client, Prop_Data, "m_iDeaths");
+}
+
+/**
+ * Sets the client's Death count.
+ *
+ * @param client Client's index.
+ * @param value Death count
+ * @noreturn
+ */
+stock Client_SetDeaths(client, value)
+{
+ SetEntProp(client, Prop_Data, "m_iDeaths", value);
+}
+
+/**
+ * Returns the client's Armor
+ *
+ * @param client Client's index.
+ * @return Armor value
+ */
+stock Client_GetArmor(client)
+{
+ return GetEntProp(client, Prop_Data, "m_ArmorValue");
+}
+
+/**
+ * Sets the client's Armor.
+ *
+ * @param client Client's index.
+ * @param value Armor value
+ * @noreturn
+ */
+stock Client_SetArmor(client, value)
+{
+ SetEntProp(client, Prop_Data, "m_ArmorValue", value);
+}
+
+/**
+ * Returns the client's Suitpower
+ *
+ * @param client Client's index.
+ * @return Suitpower
+ */
+stock Float:Client_GetSuitPower(client)
+{
+ return Float:GetEntPropFloat(client, Prop_Data, "m_flSuitPower");
+}
+
+/**
+ * Sets the client's Suitpower
+ *
+ * @param client Client's index.
+ * @param value Suitpower
+ * @noreturn
+ */
+stock Client_SetSuitPower(client, Float:value)
+{
+ SetEntPropFloat(client, Prop_Data, "m_flSuitPower", value);
+}
+
+// suit usage bits
+#define bits_SUIT_DEVICE_SPRINT 0x00000001
+#define bits_SUIT_DEVICE_FLASHLIGHT 0x00000002
+#define bits_SUIT_DEVICE_BREATHER 0x00000004
+#define MAX_SUIT_DEVICES 3
+
+/**
+ * Returns the client's active devices (Max MAX_SUIT_DEVICES)
+ * The return is a bitwise value with bits_SUIT_DEVICE_SPRINT,
+ * bits_SUIT_DEVICE_FLASHLIGHT and/or bits_SUIT_DEVICE_BREATHER set.
+ *
+ * @param client Client's index.
+ * @return The active devices (bitwise value)
+ */
+stock Client_GetActiveDevices(client)
+{
+ return GetEntProp(client, Prop_Send, "m_bitsActiveDevices");
+}
+
+/**
+ * Returns the time when the client is allowed to spray
+ * a decal again.
+ *
+ * @param client Client's index.
+ * @return Next decal time
+ */
+stock Float:Client_GetNextDecalTime(client)
+{
+ return GetEntPropFloat(client, Prop_Data, "m_flNextDecalTime");
+}
+
+/**
+ * Returns whether the client is allowed to spray a decal or not.
+ *
+ * @param client Client's index.
+ * @return True if he is allowed to spray a decal, false otherwise
+ */
+stock bool:Client_CanSprayDecal(client)
+{
+ return Client_GetNextDecalTime(client) <= GetGameTime();
+}
+
+/**
+ * Returns the vehicle the client is in, if the client
+ * isn't in a vehicle, -1 is returned.
+ *
+ * @param client Client's index.
+ * @return Vehicle index, -1 if the client isn't in a vehicle.
+ */
+stock Client_GetVehicle(client)
+{
+ new m_hVehicle = GetEntPropEnt(client, Prop_Send, "m_hVehicle");
+
+ return m_hVehicle;
+}
+
+/**
+ * Returns whether the client is in a vehicle or not.
+ *
+ * @param client Client's index.
+ * @return True if he is in a vehicle, false otherwise
+ */
+stock bool:Client_IsInVehicle(client)
+{
+ return !(Client_GetVehicle(client) == -1);
+}
+
+/**
+ * Removes all decals for a client
+ *
+ * @param client Client's index.
+ * @noreturn
+ */
+stock Client_RemoveAllDecals(client)
+{
+ ClientCommand(client, "r_cleardecals");
+}
+
+/**
+ * Let's the client exit the vehicle
+ *
+ * @param vehicle Client index.
+ * @return True on success, false otherwise.
+ */
+stock bool:Client_ExitVehicle(client)
+{
+ new vehicle = Client_GetVehicle(client);
+
+ if (vehicle == -1) {
+ return false;
+ }
+
+ return AcceptEntityInput(vehicle, "ExitVehicle");
+}
+
+/**
+ * Plays a soundfile as if the player is using voicecomm for a single client.
+ * The voiceindicator is shown on the right, as if the players is talking.
+ * Thanks to Peace-Maker for the function.
+ *
+ * @param client For whom to play the sound.
+ * @param emitter Player/Entity the voice stream comes from.
+ * @param soundfile Path to the soundfile relative to the sound folder.
+ * @param length Length in seconds how long the hud "voiceindicator" is shown.
+ * @param pitch The pitch of the audiofile.
+ * @return True on success, false on failure.
+ */
+stock bool:Client_RawAudio(client, const emitter, const String:soundfile[], Float:length = 0.0, pitch = 100)
+{
+ new Handle:message = StartMessageOne("RawAudio", client);
+
+ if (message == INVALID_HANDLE) {
+ return false;
+ }
+
+ if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available
+ && GetUserMessageType() == UM_Protobuf) {
+
+ PbSetInt(message, "pitch", pitch);
+ PbSetInt(message, "entidx", emitter);
+ PbSetFloat(message, "duration", length );
+ PbSetString(message, "voice_filename", soundfile);
+ }
+ else {
+ BfWriteByte(message, pitch);
+ BfWriteByte(message, emitter);
+ BfWriteFloat(message, length);
+ BfWriteString(message, soundfile);
+ }
+ EndMessage();
+
+ return true;
+}
+
+/**
+ * Plays a soundfile as if the player is using voicecomm for all players.
+ * The voiceindicator is shown on the right, as if the players is talking.
+ * Thanks to Peace-Maker for the function.
+ *
+ * @param emitter Player/Entity the voice stream comes from.
+ * @param soundfile Path to the soundfile relative to the sound folder.
+ * @param length Length in seconds how long the hud "voiceindicator" is shown.
+ * @param pitch The pitch of the audiofile.
+ * @return True on success, false on failure.
+ */
+stock bool:Client_RawAudioToAll(const emitter, const String:soundfile[], Float:length = 0.0, pitch = 100)
+{
+ new Handle:message = StartMessageAll("RawAudio");
+
+ if (message == INVALID_HANDLE) {
+ return false;
+ }
+
+ if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available
+ && GetUserMessageType() == UM_Protobuf) {
+
+ PbSetInt(message, "pitch", pitch);
+ PbSetInt(message, "entidx", emitter);
+ PbSetFloat(message, "duration", length);
+ PbSetString(message, "voice_filename", soundfile);
+ }
+ else {
+ BfWriteByte(message, pitch);
+ BfWriteByte(message, emitter);
+ BfWriteFloat(message, length);
+ BfWriteString(message, soundfile);
+ }
+ EndMessage();
+
+ return true;
+}
+
+/**
+ * Sets an Impulse value for a client (eg: "impulse 100" for flashlight, value would be 100).
+ * See: http://developer.valvesoftware.com/wiki/Impulse
+ *
+ * @param client Client Index
+ * @param value The impulse command value.
+ * @return True on success, false on failure.
+ */
+stock Client_Impulse(client, value)
+{
+ SetEntProp(client, Prop_Data, "m_nImpulse", value);
+}
+
+/**
+ * Gets the offset for a client's weapon list (m_hMyWeapons).
+ * The offset will saved globally for optimization.
+ *
+ * @param client Client Index.
+ * @return Weapon list offset or -1 on failure.
+ */
+stock Client_GetWeaponsOffset(client)
+{
+ static offset = -1;
+
+ if (offset == -1) {
+ offset = FindDataMapOffs(client, "m_hMyWeapons");
+ }
+
+ return offset;
+}
+
+/**
+ * Gets the current/active weapon of a client
+ *
+ * @param client Client Index.
+ * @return Weapon Index or INVALID_ENT_REFERENCE if the client has no active weapon.
+ */
+stock Client_GetActiveWeapon(client)
+{
+ new weapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon");
+
+ if (!Entity_IsValid(weapon)) {
+ return INVALID_ENT_REFERENCE;
+ }
+
+ return weapon;
+}
+
+/**
+ * Gets the classname and entity index of the current/active weapon of a client.
+ *
+ * @param client Client Index.
+ * @param buffer String Buffer to store the weapon's classname.
+ * @param size Max size of String: buffer.
+ * @return Weapon Entity Index on success or INVALID_ENT_REFERENCE otherwise
+ */
+stock Client_GetActiveWeaponName(client, String:buffer[], size)
+{
+ new weapon = Client_GetActiveWeapon(client);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ buffer[0] = '\0';
+ return INVALID_ENT_REFERENCE;
+ }
+
+ Entity_GetClassName(weapon, buffer, size);
+
+ return weapon;
+}
+
+/**
+ * Changes the active/current weapon of a player by Index.
+ * Note: No changing animation will be played !
+ *
+ * @param client Client Index.
+ * @param weapon Index of a valid weapon.
+ * @noreturn
+ */
+stock Client_SetActiveWeapon(client, weapon)
+{
+ SetEntPropEnt(client, Prop_Data, "m_hActiveWeapon", weapon);
+ ChangeEdictState(client, FindDataMapOffs(client, "m_hActiveWeapon"));
+}
+
+/**
+ * Changes the active weapon the client is holding.
+ * Note: No changing animation will be played !
+ *
+ * @param client Client Index.
+ * @param className Weapon Classname.
+ * @return True on success, false on failure.
+ */
+stock bool:Client_ChangeWeapon(client, const String:className[])
+{
+ new weapon = Client_GetWeapon(client, className);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ return false;
+ }
+
+ Client_SetActiveWeapon(client,weapon);
+
+ return true;
+}
+
+/**
+ * Changes the active weapon to the last.
+ * If the last active weapon can't be found, the default weapon is taken.
+ * If the default weapon can't be found, the first weapon in the list is taken.
+ * If the first weapon can't be found, INVALID_ENT_REFERENCEE is returned.
+ *
+ * @param client Client Index.
+ * @return Entity Index or, INVALID_ENT_REFERENCE.
+ */
+stock Client_ChangeToLastWeapon(client)
+{
+ new weapon = Client_GetLastActiveWeapon(client);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ weapon = Client_GetDefaultWeapon(client);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ weapon = Client_GetFirstWeapon(client);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ return INVALID_ENT_REFERENCE;
+ }
+ }
+ }
+
+ Client_SetActiveWeapon(client, weapon);
+
+ return weapon;
+}
+
+/**
+ * Gets the last active weapon of a client.
+ *
+ * @param client Client Index.
+ * @return Entity Index of the weapon on success, INVALID_ENT_REFERENCE on failure.
+ */
+stock Client_GetLastActiveWeapon(client)
+{
+ new weapon = GetEntPropEnt(client, Prop_Data, "m_hLastWeapon");
+
+ if (!Entity_IsValid(weapon)) {
+ return INVALID_ENT_REFERENCE;
+ }
+
+ return weapon;
+}
+
+/**
+ * Gets the classname of the last active weapon of a client.
+ *
+ * @param client Client Index.
+ * @param buffer Buffer to store the weapon classname.
+ * @param size Max size of String: buffer.
+ * @return True on success, false on failure.
+ */
+stock bool:Client_GetLastActiveWeaponName(client, String:buffer[], size)
+{
+ new weapon = Client_GetLastActiveWeapon(client);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ buffer[0] = '\0';
+ return false;
+ }
+
+ Entity_GetClassName(weapon, buffer, size);
+
+ return true;
+}
+
+/**
+ * Sets the last active weapon of a client.
+ *
+ * @param client Client Index.
+ * @param weapon Entity Index of a weapon.
+ * @noreturn
+ */
+stock Client_SetLastActiveWeapon(client, weapon)
+{
+ SetEntPropEnt(client, Prop_Data, "m_hLastWeapon", weapon);
+ ChangeEdictState(client, FindDataMapOffs(client, "m_hLastWeapon"));
+}
+
+/**
+ * Equips (attaches) a weapon to a client.
+ *
+ * @param client Client Index.
+ * @param weapon Entity Index of the weapon.
+ * @param switchTo If true, the client will switch to that weapon (make it active).
+ * @noreturn
+ */
+stock Client_EquipWeapon(client, weapon, bool:switchTo=false)
+{
+ EquipPlayerWeapon(client, weapon);
+
+ if (switchTo) {
+ Client_SetActiveWeapon(client, weapon);
+ }
+}
+
+/**
+ * Savly detaches a clients weapon, to remove it as example.
+ * The client will select his last weapon when detached.
+ *
+ * @param client Client Index.
+ * @param weapon Entity Index of the weapon, you'd like to detach.
+ * @return True on success, false otherwise.
+ */
+stock bool:Client_DetachWeapon(client, weapon)
+{
+ if (!RemovePlayerItem(client, weapon)) {
+ return false;
+ }
+
+ if (Client_GetActiveWeapon(client) == INVALID_ENT_REFERENCE) {
+ Client_ChangeToLastWeapon(client);
+ }
+
+ return true;
+}
+
+/**
+ * Gives a client a weapon.
+ *
+ * @param client Client Index.
+ * @param className Weapon Classname String.
+ * @param switchTo If set to true, the client will switch the active weapon to the new weapon.
+ * @return Entity Index of the given weapon on success, INVALID_ENT_REFERENCE on failure.
+ */
+stock Client_GiveWeapon(client, const String:className[], bool:switchTo=true)
+{
+ new weapon = Client_GetWeapon(client, className);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ weapon = Weapon_CreateForOwner(client, className);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ return INVALID_ENT_REFERENCE;
+ }
+ }
+
+ Client_EquipWeapon(client, weapon, switchTo);
+
+ return weapon;
+}
+
+/**
+ * Gives a client a weapon and ammo for that weapon.
+ *
+ * @param client Client Index.
+ * @param className Weapon Classname String.
+ * @param switchTo If set to true, the client will switch the active weapon to the new weapon.
+ * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched.
+ * @param secondaryAmmo Secondary ammo stock value from the client, if -1 the value is untouched.
+ * @param primaryClip Primary ammo value in the weapon clip, if -1 the value is untouched.
+ * @param secondaryClip Secondary ammo value in the weapon clip, if -1 the value is untouched.
+ * @return Entity Index of the given weapon on success, INVALID_ENT_REFERENCE on failure.
+ */
+stock Client_GiveWeaponAndAmmo(client, const String:className[], bool:switchTo=true, primaryAmmo=-1, secondaryAmmo=-1, primaryClip=-1, secondaryClip=-1)
+{
+ new weapon = Client_GiveWeapon(client, className, switchTo);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ return INVALID_ENT_REFERENCE;
+ }
+
+ if (primaryClip != -1) {
+ Weapon_SetPrimaryClip(weapon, primaryClip);
+ }
+
+ if (secondaryClip != -1) {
+ Weapon_SetSecondaryClip(weapon, secondaryClip);
+ }
+
+ Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo, secondaryAmmo);
+
+ return weapon;
+}
+
+/**
+ * Removes a weapon from a client.
+ *
+ * @param client Client Index.
+ * @param className Weapon Classname String.
+ * @param firstOnly If false it loops trough the whole weapon list and deletes all weapons that match the specified classname.
+ * @param clearAmmo If true, the ammo the client carries for that weapon will be set to 0 (primary and secondary).
+ * @return True on success, false otherwise.
+ */
+stock bool:Client_RemoveWeapon(client, const String:className[], bool:firstOnly=true, bool:clearAmmo=false)
+{
+ new offset = Client_GetWeaponsOffset(client) - 4;
+
+ for (new i=0; i < MAX_WEAPONS; i++) {
+ offset += 4;
+
+ new weapon = GetEntDataEnt2(client, offset);
+
+ if (!Weapon_IsValid(weapon)) {
+ continue;
+ }
+
+ if (!Entity_ClassNameMatches(weapon, className)) {
+ continue;
+ }
+
+ if (clearAmmo) {
+ Client_SetWeaponPlayerAmmoEx(client, weapon, 0, 0);
+ }
+
+ if (Client_GetActiveWeapon(client) == weapon) {
+ Client_ChangeToLastWeapon(client);
+ }
+
+ if (RemovePlayerItem(client, weapon)) {
+ Entity_Kill(weapon);
+ }
+
+ if (firstOnly) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Removes all weapons of a client.
+ * You can specify a weapon it shouldn't remove and if to
+ * clear the player's ammo for a weapon when it gets removed.
+ *
+ * @param client Client Index.
+ * @param exclude If not empty, this weapon won't be removed from the client.
+ * @param clearAmmo If true, the ammo the player carries for all removed weapons are set to 0 (primary and secondary).
+ * @return Number of removed weapons.
+ */
+stock Client_RemoveAllWeapons(client, const String:exclude[]="", bool:clearAmmo=false)
+{
+ new offset = Client_GetWeaponsOffset(client) - 4;
+
+ new numWeaponsRemoved = 0;
+ for (new i=0; i < MAX_WEAPONS; i++) {
+ offset += 4;
+
+ new weapon = GetEntDataEnt2(client, offset);
+
+ if (!Weapon_IsValid(weapon)) {
+ continue;
+ }
+
+ if (exclude[0] != '\0' && Entity_ClassNameMatches(weapon, exclude)) {
+ Client_SetActiveWeapon(client, weapon);
+ continue;
+ }
+
+ if (clearAmmo) {
+ Client_SetWeaponPlayerAmmoEx(client, weapon, 0, 0);
+ }
+
+ if (RemovePlayerItem(client, weapon)) {
+ Entity_Kill(weapon);
+ }
+
+ numWeaponsRemoved++;
+ }
+
+ return numWeaponsRemoved;
+}
+
+/**
+ * Checks if a client has a specific weapon.
+ *
+ * @param client Client Index.
+ * @param className Weapon Classname.
+ * @return True if client has the weapon, otherwise false.
+ */
+stock Client_HasWeapon(client, const String:className[])
+{
+ new weapon = Client_GetWeapon(client, className);
+
+ return (weapon != INVALID_ENT_REFERENCE);
+}
+
+/**
+ * Gets the weapon of a client by the weapon's classname.
+ *
+ * @param client Client Index.
+ * @param className Classname of the weapon.
+ * @return Entity index on success or INVALID_ENT_REFERENCE.
+ */
+stock Client_GetWeapon(client, const String:className[])
+{
+ new offset = Client_GetWeaponsOffset(client) - 4;
+ new weapon = INVALID_ENT_REFERENCE;
+ for (new i=0; i < MAX_WEAPONS; i++) {
+ offset += 4;
+
+ weapon = GetEntDataEnt2(client, offset);
+
+ if (!Weapon_IsValid(weapon)) {
+ continue;
+ }
+
+ if (Entity_ClassNameMatches(weapon, className)) {
+ return weapon;
+ }
+ }
+
+ return INVALID_ENT_REFERENCE;
+}
+
+/**
+ * Gets the weapon of a client by slot number.
+ * Note: This is incompatible to games that have multiple
+ * weapons in one slot (eg.: hl2dm).
+ *
+ * @param client Client Index.
+ * @param slot Slot Index.
+ * @return Entity index on success or INVALID_ENT_REFERENCE.
+ */
+stock Client_GetWeaponBySlot(client, slot)
+{
+ return GetPlayerWeaponSlot(client, slot);
+}
+
+/**
+ * Gets the clients default weapon (Entity Index).
+ *
+ * @param client Client Index.
+ * @return Entity Index on success, INVALID_ENT_REFERENCE on failure.
+ */
+stock Client_GetDefaultWeapon(client)
+{
+ decl String:weaponName[MAX_WEAPON_STRING];
+ if (Client_GetDefaultWeaponName(client, weaponName, sizeof(weaponName))) {
+ return INVALID_ENT_REFERENCE;
+ }
+
+ return Client_GetWeapon(client, weaponName);
+}
+
+/**
+ * Gets the clients default weapon (classname).
+ * This function doesn't work in all games (maybe only works in hl2dm).
+ * It will return an empty string if cl_defaultweapon doesn't exist.
+ *
+ * @param client Client Index.
+ * @param buffer Buffer to store the default weapon's classname.
+ * @param size Max size of string: buffer.
+ * @return True on success, false otherwise.
+ */
+stock bool:Client_GetDefaultWeaponName(client, String:buffer[], size)
+{
+ if (!GetClientInfo(client, "cl_defaultweapon", buffer, size)) {
+ buffer[0] = '\0';
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Gets the first weapon of the client's weapon list (m_hMyWeapons).
+ * Note: This has nothing to do with weapon slots.
+ *
+ * @param client Client Index.
+ * @return Entity Index of the weapon or INVALID_ENT_REFERENCE.
+ */
+stock Client_GetFirstWeapon(client)
+{
+ new offset = Client_GetWeaponsOffset(client) - 4;
+
+ for (new i=0; i < MAX_WEAPONS; i++) {
+ offset += 4;
+
+ new weapon = GetEntDataEnt2(client, offset);
+
+ if (!Weapon_IsValid(weapon)) {
+ continue;
+ }
+
+ return weapon;
+ }
+
+ return INVALID_ENT_REFERENCE;
+}
+
+/**
+ * Gets the number of weapons a client has.
+ *
+ * @param client Client Index.
+ * @return Number of weapons.
+ */
+stock Client_GetWeaponCount(client)
+{
+ new numWeapons = 0;
+
+ new offset = Client_GetWeaponsOffset(client) - 4;
+
+ for (new i=0; i < MAX_WEAPONS; i++) {
+ offset += 4;
+
+ new weapon = GetEntDataEnt2(client, offset);
+
+ if (!Weapon_IsValid(weapon)) {
+ continue;
+ }
+
+ numWeapons++;
+ }
+
+ return numWeapons;
+}
+
+/**
+ * Checks whether the client is currently reloading his active weapon.
+ *
+ * @param client Client Index.
+ * @return True if client is reloading, false otherwise.
+ */
+stock bool:Client_IsReloading(client)
+{
+ new weapon = Client_GetActiveWeapon(client);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ return false;
+ }
+
+ return Weapon_IsReloading(weapon);
+}
+
+/**
+ * Sets the primary and secondary clip value of a weapon.
+ *
+ * @param client Client Index.
+ * @param classname Classname of a weapon.
+ * @param primaryClip Primary ammo value in the weapon clip, if -1 the value is untouched.
+ * @param secondaryClip Secondary ammo value in the weapon clip, if -1 the value is untouched.
+ * @return True on success, false on failure.
+ */
+stock bool:Client_SetWeaponClipAmmo(client, const String:className[], primaryClip=-1, secondoaryClip=-1)
+{
+ new weapon = Client_GetWeapon(client, className);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ return false;
+ }
+
+ if (primaryClip != -1) {
+ Weapon_SetPrimaryClip(weapon, primaryClip);
+ }
+
+ if (secondoaryClip != -1) {
+ Weapon_SetSecondaryClip(weapon, primaryClip);
+ }
+
+ return true;
+}
+
+/**
+ * Gets the primary and secondary ammo the player carries for a specific weapon classname.
+ *
+ * @param client Client Index.
+ * @param classname Classname of a weapon.
+ * @param primaryAmmo Primary ammo stock from the client, if -1 the value is untouched.
+ * @param secondaryAmmo Secondary ammo stock from the client, if -1 the value is untouched.
+ * @return True on success, false on failure.
+ */
+stock bool:Client_GetWeaponPlayerAmmo(client, const String:className[], &primaryAmmo=-1, &secondaryAmmo=-1)
+{
+ new weapon = Client_GetWeapon(client, className);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ return false;
+ }
+
+ new offset_ammo = FindDataMapOffs(client, "m_iAmmo");
+
+ if (primaryAmmo != -1) {
+ new offset = offset_ammo + (Weapon_GetPrimaryAmmoType(weapon) * 4);
+ primaryAmmo = GetEntData(client, offset);
+ }
+
+ if (secondaryAmmo != -1) {
+ new offset = offset_ammo + (Weapon_GetSecondaryAmmoType(weapon) * 4);
+ secondaryAmmo = GetEntData(client, offset);
+ }
+
+ return true;
+}
+
+/**
+ * Gets the primary and secondary ammo the player carries for a specific weapon index.
+ *
+ * @param client Client Index.
+ * @param weapon Weapon Entity Index.
+ * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched.
+ * @param secondaryAmmo Secondary ammo stock value from the client, if -1 the value is untouched.
+ * @noreturn
+ */
+stock Client_GetWeaponPlayerAmmoEx(client, weapon, &primaryAmmo=-1, &secondaryAmmo=-1)
+{
+ new offset_ammo = FindDataMapOffs(client, "m_iAmmo");
+
+ if (primaryAmmo != -1) {
+ new offset = offset_ammo + (Weapon_GetPrimaryAmmoType(weapon) * 4);
+ primaryAmmo = GetEntData(client, offset);
+ }
+
+ if (secondaryAmmo != -1) {
+ new offset = offset_ammo + (Weapon_GetSecondaryAmmoType(weapon) * 4);
+ secondaryAmmo = GetEntData(client, offset);
+ }
+}
+
+/**
+ * Sets the primary and secondary ammo the player carries for a specific weapon classname.
+ *
+ * @param client Client Index.
+ * @param classname Weapon Classname String.
+ * @param primaryAmmo Primary ammo stock from the client, if -1 the value is untouched.
+ * @param secondaryAmmo Secondary ammo stock from the client, if -1 the value is untouched.
+ * @return True on success, false on failure.
+ */
+stock bool:Client_SetWeaponPlayerAmmo(client, const String:className[], primaryAmmo=-1, secondaryAmmo=-1)
+{
+ new weapon = Client_GetWeapon(client, className);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ return false;
+ }
+
+ Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo, secondaryAmmo);
+
+ return true;
+}
+
+/**
+ * Sets the primary and secondary ammo the player carries for a specific weapon index.
+ *
+ * @param client Client Index.
+ * @param weapon Weapon Entity Index.
+ * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched.
+ * @param secondaryAmmo Secondary ammo stock value from the client, if -1 the value is untouched.
+ * @noreturn
+ */
+stock Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo=-1, secondaryAmmo=-1)
+{
+ new offset_ammo = FindDataMapOffs(client, "m_iAmmo");
+
+ if (primaryAmmo != -1) {
+ new offset = offset_ammo + (Weapon_GetPrimaryAmmoType(weapon) * 4);
+ SetEntData(client, offset, primaryAmmo, 4, true);
+ }
+
+ if (secondaryAmmo != -1) {
+ new offset = offset_ammo + (Weapon_GetSecondaryAmmoType(weapon) * 4);
+ SetEntData(client, offset, secondaryAmmo, 4, true);
+ }
+}
+
+/**
+ * Sets the value from primary and secondary ammo stock, of a client.
+ *
+ * @param client Client Index.
+ * @param className Classname of a weapon.
+ * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched.
+ * @param secondaryAmmo Secondary ammo stock value from the client, if -1 the value is untouched.
+ * @param primaryClip Primary ammo value in the weapon clip, if -1 the value is untouched.
+ * @param secondaryClip Secondary ammo value in the weapon clip, if -1 the value is untouched.
+ * @return Entity Index of the given weapon on success, INVALID_ENT_REFERENCE on failure.
+ */
+stock Client_SetWeaponAmmo(client, const String:className[], primaryAmmo=-1, secondaryAmmo=-1, primaryClip=-1, secondaryClip=-1)
+{
+ new weapon = Client_GetWeapon(client, className);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ return false;
+ }
+
+ if (primaryClip != -1) {
+ Weapon_SetPrimaryClip(weapon, primaryClip);
+ }
+ if (secondaryClip != -1) {
+ Weapon_SetSecondaryClip(weapon, secondaryClip);
+ }
+ Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo, secondaryAmmo);
+
+ return true;
+}
+
+/**
+ * Gets the next weapon of a client, starting at start.
+ *
+ * @param client Client Index (must be a valid client ingame).
+ * @param index Reference to an index variable, will contain the index of the next weapon to check.
+ * @return Weapon Index or -1 if no more weapons are found.
+ */
+stock Client_GetNextWeapon(client, &index = 0)
+{
+ new offset = Client_GetWeaponsOffset(client) + (index * 4);
+
+ new weapon;
+ while (index < MAX_WEAPONS) {
+ index++;
+
+ weapon = GetEntDataEnt2(client, offset);
+
+ if (Weapon_IsValid(weapon)) {
+ return weapon;
+ }
+
+ offset += 4;
+ }
+
+ return -1;
+}
+
+/**
+ * Prints white text to the bottom center of the screen
+ * for one client. Does not work in all games.
+ * Line Breaks can be done with "\n".
+ *
+ * @param client Client Index.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @return True on success, false if this usermessage doesn't exist.
+ */
+stock bool:Client_PrintHintText(client, const String:format[], any:...)
+{
+ new Handle:userMessage = StartMessageOne("HintText", client);
+
+ if (userMessage == INVALID_HANDLE) {
+ return false;
+ }
+
+ decl String:buffer[254];
+
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), format, 3);
+
+
+ if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available
+ && GetUserMessageType() == UM_Protobuf) {
+
+ PbSetString(userMessage, "text", format);
+ }
+ else {
+ BfWriteByte(userMessage, 1);
+ BfWriteString(userMessage, buffer);
+ }
+
+ EndMessage();
+
+ return true;
+}
+
+/**
+ * Prints white text to the bottom center of the screen
+ * for all clients. Does not work in all games.
+ * Line Breaks can be done with "\n".
+ *
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock Client_PrintHintTextToAll(const String:format[], any:...)
+{
+ decl String:buffer[254];
+
+ for (new client=1; client <= MaxClients; client++) {
+
+ if (!IsClientInGame(client)) {
+ continue;
+ }
+
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), format, 2);
+ Client_PrintHintText(client, buffer);
+ }
+}
+
+/**
+ * Prints white text to the right-center side of the screen
+ * for one client. Does not work in all games.
+ * Line Breaks can be done with "\n".
+ *
+ * @param client Client Index.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @return True on success, false if this usermessage doesn't exist.
+ */
+stock bool:Client_PrintKeyHintText(client, const String:format[], any:...)
+{
+ new Handle:userMessage = StartMessageOne("KeyHintText", client);
+
+ if (userMessage == INVALID_HANDLE) {
+ return false;
+ }
+
+ decl String:buffer[254];
+
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), format, 3);
+
+ if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available
+ && GetUserMessageType() == UM_Protobuf) {
+
+ PbSetString(userMessage, "hints", buffer);
+ }
+ else {
+ BfWriteByte(userMessage, 1);
+ BfWriteString(userMessage, buffer);
+ }
+
+ EndMessage();
+
+ return true;
+}
+
+/**
+ * Prints white text to the right-center side of the screen
+ * for all clients. Does not work in all games.
+ * Line Breaks can be done with "\n".
+ *
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock Client_PrintKeyHintTextToAll(const String:format[], any:...)
+{
+ decl String:buffer[254];
+
+ for (new client=1; client <= MaxClients; client++) {
+
+ if (!IsClientInGame(client)) {
+ continue;
+ }
+
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), format, 2);
+ Client_PrintKeyHintText(client, buffer);
+ }
+}
+
+/**
+ * Prints a reliable raw chat message to a client in the chat area.
+ * If the client == 0, the message will printed to server console.
+ *
+ * @param client Client Index.
+ * @param message String Message.
+ * @param subject Client Index/Subject (normally used for teamcolors)
+ * @param isChat Tells the game to handle the chat as normal (false) or chat message (true, plays a sound), only works if SayText2 is supported.
+ * @noreturn
+ */
+stock Client_PrintToChatRaw(client, const String:message[], subject=0, bool:isChat=false)
+{
+ if (client == 0) {
+ decl String:buffer[253];
+ Color_StripFromChatText(message, buffer, sizeof(buffer));
+ PrintToServer(buffer);
+ return;
+ }
+
+ static sayText2_supported = true;
+ static sayText2_checked = false;
+
+ if (!sayText2_checked) {
+
+ if (GetUserMessageId("SayText2") == INVALID_MESSAGE_ID) {
+ sayText2_supported = false;
+ }
+
+ sayText2_checked = true;
+ }
+
+ new Handle:userMessage = INVALID_HANDLE;
+
+ if (sayText2_supported) {
+ userMessage = StartMessageOne("SayText2", client, USERMSG_RELIABLE);
+
+ if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available
+ && GetUserMessageType() == UM_Protobuf) {
+
+ PbSetInt(userMessage, "ent_idx", subject);
+ PbSetBool(userMessage, "chat", isChat);
+ PbSetString(userMessage, "msg_name", message);
+
+ // psychonic: Furthermore, some usermessages with repeated field,
+ // such as the commonly-used SayText2, expected an undocumented
+ // specific number of values added, else the client will crash when receiving.
+ PbAddString(userMessage, "params", "");
+ PbAddString(userMessage, "params", "");
+ PbAddString(userMessage, "params", "");
+ PbAddString(userMessage, "params", "");
+ }
+ else {
+ BfWriteByte(userMessage , subject);
+ BfWriteByte(userMessage , isChat);
+ BfWriteString(userMessage , message);
+ }
+ }
+ else {
+ userMessage = StartMessageOne("SayText", client, USERMSG_RELIABLE);
+
+ if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available
+ && GetUserMessageType() == UM_Protobuf) {
+
+ PbSetInt(userMessage, "ent_idx", subject);
+ PbSetString(userMessage, "text", message);
+ PbSetBool(userMessage, "chat", isChat);
+ }
+ else {
+ BfWriteByte(userMessage , subject);
+ BfWriteString(userMessage , message);
+ // For DoD:S nickname coloring
+ BfWriteByte(userMessage , -1);
+ }
+ }
+
+ EndMessage();
+}
+
+/**
+ * Prints a reliable chat message to one client in the chat area.
+ * Allows up to 253 Characters (including \0) to be printed.
+ * Supports chat color tags (see: colors.inc).
+ *
+ * @param client Client Index.
+ * @param isChat Tells the game to handle the chat as normal (false) or chat message (true, plays a sound), only works if SayText2 is supported.
+ * @param format Formatting rules String.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock Client_PrintToChat(client, bool:isChat, const String:format[], any:...)
+{
+ decl
+ String:buffer[512],
+ String:buffer2[253];
+
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), format, 4);
+ new subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2));
+
+ Client_PrintToChatRaw(client, buffer2, subject, isChat);
+
+ Color_ChatClearSubject();
+}
+
+static printToChat_excludeclient = -1;
+
+/**
+ * Exclude a client from the next call to a Client_PrintToChat function.
+ *
+ * @param client Client Index.
+ * @noreturn
+ */
+stock Client_PrintToChatExclude(client)
+{
+ printToChat_excludeclient = client;
+}
+
+/**
+ * Prints a reliable chat message to all clients in the chat area.
+ * Allows up to 253 Characters (including \0) to be printed.
+ * Supports chat color tags (see: colors.inc).
+ *
+ * @param isChat Tells the game to handle the chat as normal (false) or chat message (true, plays a sound), only works if SayText2 is supported.
+ * @param format Formatting rules String.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock Client_PrintToChatAll(bool:isChat, const String:format[], any:...)
+{
+ decl
+ String:buffer[512],
+ String:buffer2[253];
+ new
+ subject,
+ language,
+ lastLanguage = -1;
+
+ for (new client=1; client <= MaxClients; client++) {
+
+ if (!IsClientInGame(client)) {
+ continue;
+ }
+
+ if (client == printToChat_excludeclient) {
+ printToChat_excludeclient = -1;
+ continue;
+ }
+
+ language = GetClientLanguage(client);
+
+ if (language != lastLanguage) {
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), format, 3);
+ subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2));
+
+ lastLanguage = language;
+ }
+
+ Client_PrintToChatRaw(client, buffer2, subject, isChat);
+ }
+
+ Color_ChatClearSubject();
+}
+
+/**
+ * Prints a reliable chat message to the specified clients in the chat area.
+ * Allows up to 253 Characters (including \0) to be print.
+ * Supports chat color tags (see: colors.inc).
+ *
+ * @param clients Client Array.
+ * @param numClients Number of clients in the client array.
+ * @param isChat Tells the game to handle the chat as normal (false) or chat message (true, plays a sound), only works if SayText2 is supported.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock Client_PrintToChatEx(clients[], numClients, bool:isChat, const String:format[], any:...)
+{
+ decl
+ String:buffer[512],
+ String:buffer2[253];
+ new
+ client,
+ subject,
+ language,
+ lastLanguage = -1;
+
+ for (new i=0; i < numClients; i++) {
+
+ client = clients[i];
+
+ if (!IsClientInGame(client)) {
+ continue;
+ }
+
+ if (client == printToChat_excludeclient) {
+ printToChat_excludeclient = -1;
+ continue;
+ }
+
+ language = GetClientLanguage(client);
+
+ if (language != lastLanguage) {
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), format, 5);
+ subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2));
+
+ lastLanguage = language;
+ }
+
+ Client_PrintToChatRaw(client, buffer2, subject, isChat);
+ }
+
+ Color_ChatClearSubject();
+}
+
+enum ClientHudPrint {
+ ClientHudPrint_Notify = 1,
+ ClientHudPrint_Console,
+ ClientHudPrint_Talk,
+ Client_HudPrint_Center
+};
+
+/**
+ * Prints a relieable message to the client's console.
+ * Allows up to 254 Characters (including \0) to be print (253 for talk).
+ * Supports chat color tags (see: colors.inc, only available in Left 4 Dead (2) or higher).
+ * Chat colors are stripped automatically if not supported.
+ *
+ * @param clients Client Array.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock Client_PrintToConsole(client, const String:format[], any:...)
+{
+ decl String:buffer[512];
+
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), format, 3);
+
+ Client_Print(client, ClientHudPrint_Console, buffer);
+}
+
+/**
+ * Prints a relieable message to the client's console.
+ * Allows up to 254 Characters (including \0) to be print.
+ * Supports chat color tags in chat & console (see: colors.inc).
+ * Chat colors are stripped automatically if not supported in the destination.
+ *
+ * @param clients Client Array.
+ * @param destination Destination place (use onf of the ClientHudPrint_)
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock Client_Print(client, ClientHudPrint:destination, const String:format[], any:...)
+{
+ decl String:buffer[512], String:buffer2[254];
+
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), format, 4);
+
+ new subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2));
+
+ if (destination == ClientHudPrint_Talk) {
+ Client_PrintToChatRaw(client, buffer2, subject, false);
+ return;
+ }
+
+ new EngineVersion:engineVersion = GetEngineVersion();
+ if (client == 0 ||
+ destination != ClientHudPrint_Console ||
+ (destination == ClientHudPrint_Console
+ && engineVersion != Engine_Left4Dead && engineVersion != Engine_Left4Dead2))
+ {
+ Color_StripFromChatText(buffer2, buffer2, sizeof(buffer2));
+
+ if (client == 0) {
+ PrintToServer(buffer2);
+ return;
+ }
+ }
+
+ new Handle:userMessage = INVALID_HANDLE;
+ userMessage = StartMessageOne("TextMsg", client, USERMSG_RELIABLE);
+
+ if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available
+ && GetUserMessageType() == UM_Protobuf) {
+
+ PbSetInt(userMessage, "msg_dst", _:destination);
+ PbAddString(userMessage, "params", buffer2);
+ PbAddString(userMessage, "params", "");
+ PbAddString(userMessage, "params", "");
+ PbAddString(userMessage, "params", "");
+ PbAddString(userMessage, "params", "");
+ }
+ else {
+ BfWriteByte(userMessage , _:destination);
+ BfWriteString(userMessage , buffer2);
+ }
+
+ EndMessage();
+}
+
+/**
+ * Replies to a message in a command.
+ * A client index of 0 will use PrintToServer().
+ * If the command was from the console, Client_PrintToConsole() is used.
+ * If the command was from chat, Client_PrintToChat() is used.
+ *
+ * @param client Client Index.
+ * @param format Formatting rules String.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock Client_Reply(client, const String:format[], any:...)
+{
+ decl String:buffer[255];
+
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), format, 3);
+
+ if (GetCmdReplySource() == SM_REPLY_TO_CONSOLE) {
+ Client_PrintToConsole(client, buffer);
+ }
+ else {
+ Client_PrintToChat(client, false, buffer);
+ }
+}
+
+#define SHAKE_START 0 // Starts the screen shake for all players within the radius.
+#define SHAKE_STOP 1 // Stops the screen shake for all players within the radius.
+#define SHAKE_AMPLITUDE 2 // Modifies the amplitude of an active screen shake for all players within the radius.
+#define SHAKE_FREQUENCY 3 // Modifies the frequency of an active screen shake for all players within the radius.
+#define SHAKE_START_RUMBLEONLY 4 // Starts a shake effect that only rumbles the controller, no screen effect.
+#define SHAKE_START_NORUMBLE 5 // Starts a shake that does NOT rumble the controller.
+
+/**
+ * Shakes a client's screen with the specified amptitude,
+ * frequency & duration.
+ *
+ * @param client Client Index.
+ * @param command Shake Mode, use one of the SHAKE_ definitions.
+ * @param amplitude Shake magnitude/amplitude.
+ * @param frequency Shake noise frequency.
+ * @param duration Shake lasts this long.
+ * @return True on success, false otherwise.
+ */
+stock bool:Client_Shake(client, command=SHAKE_START, Float:amplitude=50.0, Float:frequency=150.0, Float:duration=3.0)
+{
+ if (command == SHAKE_STOP) {
+ amplitude = 0.0;
+ }
+ else if (amplitude <= 0.0) {
+ return false;
+ }
+
+ new Handle:userMessage = StartMessageOne("Shake", client);
+
+ if (userMessage == INVALID_HANDLE) {
+ return false;
+ }
+
+ if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available
+ && GetUserMessageType() == UM_Protobuf) {
+
+ PbSetInt(userMessage, "command", command);
+ PbSetFloat(userMessage, "local_amplitude", amplitude);
+ PbSetFloat(userMessage, "frequency", frequency);
+ PbSetFloat(userMessage, "duration", duration);
+ }
+ else {
+ BfWriteByte(userMessage, command); // Shake Command
+ BfWriteFloat(userMessage, amplitude); // shake magnitude/amplitude
+ BfWriteFloat(userMessage, frequency); // shake noise frequency
+ BfWriteFloat(userMessage, duration); // shake lasts this long
+ }
+
+ EndMessage();
+
+ return true;
+}
+
+/**
+ * Checks whether the client is a generic admin.
+ *
+ * @param Client Index.
+ * @return True if the client is a generic admin, false otheriwse.
+ */
+stock bool:Client_IsAdmin(client)
+{
+ new AdminId:adminId = GetUserAdmin(client);
+
+ if (adminId == INVALID_ADMIN_ID) {
+ return false;
+ }
+
+ return GetAdminFlag(adminId, Admin_Generic);
+}
+
+/**
+ * Checks whether a client has certain admin flags
+ *
+ * @param Client Index.
+ * @return True if the client has the admin flags, false otherwise.
+ */
+stock bool:Client_HasAdminFlags(client, flags=ADMFLAG_GENERIC)
+{
+ new AdminId:adminId = GetUserAdmin(client);
+
+ if (adminId == INVALID_ADMIN_ID) {
+ return false;
+ }
+
+ return bool:(GetAdminFlags(adminId, Access_Effective) & flags);
+}
+
+/**
+ * Returns whether a player is in a specific admin group.
+ *
+ * @param client Client Index.
+ * @param groupName Admin group name to check.
+ * @param caseSensitive True if the group check has to be case sensitive, false otherwise.
+ * @return True if the client is in the admin group, false otherwise.
+ */
+stock bool:Client_IsInAdminGroup(client, const String:groupName[], bool:caseSensitive=true)
+{
+ new AdminId:adminId = GetUserAdmin(client);
+
+ // Validate id.
+ if (adminId == INVALID_ADMIN_ID) {
+ return false;
+ }
+
+ // Get number of groups.
+ new count = GetAdminGroupCount(adminId);
+
+ // Validate number of groups.
+ if (count == 0) {
+ return false;
+ }
+
+ decl String:groupname[64];
+
+ // Loop through each group.
+ for (new i = 0; i < count; i++) {
+ // Get group name.
+ GetAdminGroup(adminId, i, groupname, sizeof(groupname));
+
+ // Compare names.
+ if (StrEqual(groupName, groupname, caseSensitive)) {
+ return true;
+ }
+ }
+
+ // No match.
+ return false;
+}
+
+/**
+ * Checks if the client is currently looking at the wall in front
+ * of him with the given distance as max value.
+ *
+ * @param client Client Index.
+ * @param distance Max Distance as Float value.
+ * @return True if he is looking at a wall, false otherwise.
+ */
+stock bool:Client_IsLookingAtWall(client, Float:distance=40.0) {
+
+ decl Float:posEye[3], Float:posEyeAngles[3];
+ new bool:isClientLookingAtWall = false;
+
+ GetClientEyePosition(client, posEye);
+ GetClientEyeAngles(client, posEyeAngles);
+
+ posEyeAngles[0] = 0.0;
+
+ new Handle:trace = TR_TraceRayFilterEx(posEye, posEyeAngles, CONTENTS_SOLID, RayType_Infinite, _smlib_TraceEntityFilter);
+
+ if (TR_DidHit(trace)) {
+
+ if (TR_GetEntityIndex(trace) > 0) {
+ CloseHandle(trace);
+ return false;
+ }
+
+ decl Float:posEnd[3];
+
+ TR_GetEndPosition(posEnd, trace);
+
+ if (GetVectorDistance(posEye, posEnd, true) <= (distance * distance)) {
+ isClientLookingAtWall = true;
+ }
+ }
+
+ CloseHandle(trace);
+
+ return isClientLookingAtWall;
+}
+
+public bool:_smlib_TraceEntityFilter(entity, contentsMask)
+{
+ return entity == 0;
+}
+
+/**
+ * Gets a client's class.
+ * Currently supported games are: TF2, Dark Messiah.
+ * Other games maybe work too, but are not tested.
+ *
+ * @param client Client Index.
+ * @return Class Index.
+ */
+stock Client_GetClass(client)
+{
+ if (GetEngineVersion() == Engine_DarkMessiah) {
+ return GetEntProp(client, Prop_Send, "m_iPlayerClass");
+ }
+
+ return GetEntProp(client, Prop_Send, "m_iClass");
+}
+
+/**
+ * Sets a client's class.
+ * Currently supported games are: TF2, Dark Messiah.
+ * Other games maybe work too, but are not tested.
+ *
+ * @param client Client Index.
+ * @param playerClass The class number to set the player to. Depends on game.
+ * @param persistant If true changes the players desired class so the change stays after death (probably TF2 only).
+ * @return Class Index.
+ */
+stock Client_SetClass(client, playerClass, bool:persistant=false)
+{
+ if (GetEngineVersion() == Engine_DarkMessiah) {
+ SetEntProp(client, Prop_Send, "m_iPlayerClass", playerClass);
+ } else {
+ SetEntProp(client, Prop_Send, "m_iClass", playerClass);
+
+ if (persistant) {
+ SetEntProp(client, Prop_Send, "m_iDesiredPlayerClass", playerClass);
+ }
+ }
+}
+
+/**
+ * Returns what buttons are currently pressed by the client.
+ *
+ * @param client Client Index.
+ * @return Buttons as bitflag.
+ */
+stock Client_GetButtons(client)
+{
+ return GetClientButtons(client);
+}
+
+/**
+ * Sets the client buttons.
+ * Note: This will only work OnPreThink (sdkhooks) or OnPlayerRunCmd.
+ *
+ * @param client Client Index.
+ * @param buttons Buttons as bitflag.
+ * @noreturn
+ */
+stock Client_SetButtons(client, buttons)
+{
+ SetEntProp(client, Prop_Data, "m_nButtons", buttons);
+}
+
+/**
+ * Adds buttons to the already pressed buttons.
+ * Note: This will likely only work OnPreThink (sdkhooks) or OnPlayerRunCmd.
+ *
+ * @param client Client Index.
+ * @param buttons Buttons as bitflag.
+ * @noreturn
+ */
+stock Client_AddButtons(client, buttons)
+{
+ new newButtons = Client_GetButtons(client);
+ newButtons |= buttons;
+ Client_SetButtons(client, newButtons);
+}
+
+/**
+ * Removes buttons from the already pressed buttons.
+ * Note: This will only work OnPreThink (sdkhooks) or OnPlayerRunCmd.
+ *
+ * @param client Client Index.
+ * @param buttons Buttons as bitflag.
+ * @noreturn
+ */
+stock Client_RemoveButtons(client, buttons)
+{
+ new newButtons = Client_GetButtons(client);
+ newButtons &= ~buttons;
+ Client_SetButtons(client, newButtons);
+}
+
+/**
+ * Clears all buttons.
+ * Note: This will likely only work OnPreThink (sdkhooks) or OnPlayerRunCmd.
+ *
+ * @param client Client Index.
+ * @noreturn
+ */
+stock Client_ClearButtons(client)
+{
+ Client_SetButtons(client,0);
+}
+
+/**
+ * Returns if the given buttons are pressed by the client or not.
+ *
+ * @param client Client Index.
+ * @param buttons Buttons as bitflag.
+ * @return True if the buttons are pressed otherwise false.
+ */
+stock bool:Client_HasButtons(client, buttons)
+{
+ return bool:(Client_GetButtons(client) & buttons);
+}
+
+/**
+ * Returns only the buttons that have changed since the last call of this.
+ * Example usage: Within OnPlayerRunCmd use this function to call another function only once when a player pressed or released a button.
+ *
+ * @param client Client Index.
+ * @param buttons Buttons as bitflag.
+ * @return
+ */
+stock Client_GetChangedButtons(client)
+{
+ static oldButtons[MAXPLAYERS+1] = {0,...};
+
+ new buttons = Client_GetButtons(client);
+ new changedButtons = buttons ^ oldButtons[client];
+
+ oldButtons[client] = buttons;
+
+ return changedButtons;
+}
+
+/**
+ * Sets the client's maxspeed to the given value (in units per second)
+ *
+ * @param Client Client Index
+ * @param maxspeed the maximum speed the client can move
+ * @noreturn
+ */
+stock Client_SetMaxSpeed(client, Float:value)
+{
+ Entity_SetMaxSpeed(client, value);
+}
+
+/**
+ * Shows a screen overlay tp a client.
+ * There can only be one overlay at a time.
+ * If you want to clear the overlay, pass
+ * an empty string to this function.
+ *
+ * @param Client Client Index.
+ * @param path Overlay path (based on the game/materials/ folder) or empty String to not show any overlay.
+ * @noreturn
+ */
+stock Client_SetScreenOverlay(client, const String:path[])
+{
+ ClientCommand(client, "r_screenoverlay \"%s\"", path);
+}
+
+/**
+ * Shows a screen overlay to all clients.
+ * There can only be one overlay at a time.
+ * If you want to clear the overlay, pass
+ * an empty string to this function.
+ *
+ * @param Client Client Index.
+ * @param path Overlay path (based on the game/materials/ folder) or empty String to not show any overlay.
+ * @noreturn
+ */
+stock Client_SetScreenOverlayForAll(const String:path[])
+{
+ LOOP_CLIENTS(client, CLIENTFILTER_INGAME | CLIENTFILTER_NOBOTS) {
+ Client_SetScreenOverlay(client, path);
+ }
+}
+
+/**
+ * Mutes a client's voice
+ *
+ * @param Client Client Index.
+ * @noreturn
+ */
+stock Client_Mute(client)
+{
+ SetClientListeningFlags(client, VOICE_MUTED);
+}
+
+/**
+ * UnMutes a client's voice
+ * Code copied from basecomm.sp
+ *
+ * @param Client Client Index.
+ * @noreturn
+ */
+stock Client_UnMute(client)
+{
+ static Handle:cvDeadTalk = INVALID_HANDLE;
+
+ if (cvDeadTalk == INVALID_HANDLE) {
+ cvDeadTalk = FindConVar("sm_deadtalk");
+ }
+
+ if (cvDeadTalk == INVALID_HANDLE) {
+ SetClientListeningFlags(client, VOICE_NORMAL);
+ }
+ else {
+ if (GetConVarInt(cvDeadTalk) == 1 && !IsPlayerAlive(client)) {
+ SetClientListeningFlags(client, VOICE_LISTENALL);
+ }
+ else if (GetConVarInt(cvDeadTalk) == 2 && !IsPlayerAlive(client)) {
+ SetClientListeningFlags(client, VOICE_TEAM);
+ }
+ else {
+ SetClientListeningFlags(client, VOICE_NORMAL);
+ }
+ }
+}
+
+/**
+ * Checks if a client's voice is muted
+ *
+ * @param Client Client Index.
+ * @return True if the client is muted, false otherwise.
+ */
+stock bool:Client_IsMuted(client)
+{
+ return bool:(GetClientListeningFlags(client) & VOICE_MUTED);
+}
+
+/**
+ * Checks if a client matches the specified flag filter.
+ * Use one of the CLIENTFILTER_ constants.
+ * Note that this already checks if the client is ingame or connected
+ * so you don't have to do that yourself.
+ * This function is optimized to make as less native calls as possible :)
+ *
+ * @param Client Client Index.
+ * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants).
+ * @return True if the client if the client matches, false otherwise.
+ */
+stock bool:Client_MatchesFilter(client, flags)
+{
+ new bool:isIngame = false;
+
+ if (flags >= CLIENTFILTER_INGAME) {
+ isIngame = IsClientInGame(client);
+
+ if (isIngame) {
+ if (flags & CLIENTFILTER_NOTINGAME) {
+ return false;
+ }
+ }
+ else {
+ return false;
+ }
+ }
+ else if (!IsClientConnected(client)) {
+ return false;
+ }
+
+ if (!flags) {
+ return true;
+ }
+
+ if (flags & CLIENTFILTER_INGAMEAUTH) {
+ flags |= CLIENTFILTER_INGAME | CLIENTFILTER_AUTHORIZED;
+ }
+
+ if (flags & CLIENTFILTER_BOTS && !IsFakeClient(client)) {
+ return false;
+ }
+
+ if (flags & CLIENTFILTER_NOBOTS && IsFakeClient(client)) {
+ return false;
+ }
+
+ if (flags & CLIENTFILTER_ADMINS && !Client_IsAdmin(client)) {
+ return false;
+ }
+
+ if (flags & CLIENTFILTER_NOADMINS && Client_IsAdmin(client)) {
+ return false;
+ }
+
+ if (flags & CLIENTFILTER_AUTHORIZED && !IsClientAuthorized(client)) {
+ return false;
+ }
+
+ if (flags & CLIENTFILTER_NOTAUTHORIZED && IsClientAuthorized(client)) {
+ return false;
+ }
+
+ if (isIngame) {
+
+ if (flags & CLIENTFILTER_ALIVE && !IsPlayerAlive(client)) {
+ return false;
+ }
+
+ if (flags & CLIENTFILTER_DEAD && IsPlayerAlive(client)) {
+ return false;
+ }
+
+ if (flags & CLIENTFILTER_SPECTATORS && GetClientTeam(client) != TEAM_SPECTATOR) {
+ return false;
+ }
+
+ if (flags & CLIENTFILTER_NOSPECTATORS && GetClientTeam(client) == TEAM_SPECTATOR) {
+ return false;
+ }
+
+ if (flags & CLIENTFILTER_OBSERVERS && !IsClientObserver(client)) {
+ return false;
+ }
+
+ if (flags & CLIENTFILTER_NOOBSERVERS && IsClientObserver(client)) {
+ return false;
+ }
+
+ if (flags & CLIENTFILTER_TEAMONE && GetClientTeam(client) != TEAM_ONE) {
+ return false;
+ }
+
+ if (flags & CLIENTFILTER_TEAMTWO && GetClientTeam(client) != TEAM_TWO) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Gets all clients matching the specified flags filter.
+ *
+ * @param client Client Array, size should be MaxClients or MAXPLAYERS
+ * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants).
+ * @return The number of clients stored in the array
+ */
+stock Client_Get(clients[], flags=CLIENTFILTER_ALL)
+{
+ new x=0;
+ for (new client = 1; client <= MaxClients; client++) {
+
+ if (!Client_MatchesFilter(client, flags)) {
+ continue;
+ }
+
+ clients[x++] = client;
+ }
+
+ return x;
+}
+
+/**
+ * Gets a random client matching the specified flags filter.
+ *
+ * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants).
+ * @return Client Index or -1 if no client was found
+ */
+stock Client_GetRandom(flags=CLIENTFILTER_ALL)
+{
+ decl clients[MaxClients];
+ new num = Client_Get(clients, flags);
+
+ if (num == 0) {
+ return -1;
+ }
+ else if (num == 1) {
+ return clients[0];
+ }
+
+ new random = Math_GetRandomInt(0, num-1);
+
+ return clients[random];
+}
+
+/**
+ * Gets a client matching certain flags starting at start.
+ *
+ * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants).
+ * @param start Start Index.
+ * @return Client Index or -1 if no client was found
+ */
+stock Client_GetNext(flags, start=1)
+{
+ for (new client=start; client <= MaxClients; client++) {
+
+ if (Client_MatchesFilter(client, flags)) {
+ return client;
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * Retrieves the time duration a client played on the current map.
+ *
+ * @param client Client Index.
+ * @return Time in seconds as Float
+ */
+stock Float:Client_GetMapTime(client)
+{
+ new Float:fClientTime = GetClientTime(client);
+ new Float:fGameTime = GetGameTime();
+
+ return (fClientTime < fGameTime) ? fClientTime : fGameTime;
+}
+
+/**
+ * Gets client money value (for games like Counter-Strike:Source).
+ *
+ * @param client Client Index.
+ * @return Money value from the client.
+ */
+stock Client_GetMoney(client)
+{
+ return GetEntProp(client, Prop_Send, "m_iAccount");
+}
+
+/**
+ * Sets client money value (for games like Counter-Strike:Source).
+ *
+ * @param client Client Index.
+ * @param value Money value to set.
+ * @noreturn
+ */
+stock Client_SetMoney(client, value)
+{
+ SetEntProp(client, Prop_Send, "m_iAccount", value);
+}
+
+/**
+ * Gets a client's observers.
+ *
+ * @param client Client Index.
+ * @param observers Array with size of MaxClients or MAXPLAYERS.
+ * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants).
+ * @return Number of observers found.
+ */
+stock Client_GetObservers(client, observers[], flags=CLIENTFILTER_ALL)
+{
+ new count = 0;
+
+ LOOP_CLIENTS(player, CLIENTFILTER_OBSERVERS | flags) {
+
+ if (Client_GetObserverTarget(player) == client) {
+ observers[count++] = player;
+ }
+ }
+
+ return count;
+}
+
+static Float:getPlayersInRadius_distances[MAXPLAYERS+1];
+
+/**
+ * Gets all players near a player in a certain radius and
+ * orders the players by distance (optional).
+ *
+ * @param client Client Index.
+ * @param clients Array with size of MaxClients or MAXPLAYERS.
+ * @param radius radius Float (max distance)
+ * @param orderByDistance Set to true to order the clients by distance, false otherwise.
+ * @return Number of clients found.
+ */
+stock Client_GetPlayersInRadius(client, clients[], Float:radius, bool:orderByDistance=true)
+{
+ decl Float:origin_client[3];
+ new
+ Float:distance,
+ count=0;
+
+ Entity_GetAbsOrigin(client, origin_client);
+
+ LOOP_CLIENTS(player, CLIENTFILTER_INGAME) {
+
+ if (player == client) {
+ continue;
+ }
+
+ distance = Entity_GetDistanceOrigin(player, origin_client);
+
+ if (distance <= radius) {
+ clients[count++] = player;
+
+ if (orderByDistance) {
+ getPlayersInRadius_distances[player] = distance;
+ }
+ }
+ }
+
+ if (orderByDistance) {
+ SortCustom1D(clients, count, __smlib_GetPlayersInRadius_Sort);
+ }
+
+ return count;
+}
+
+public __smlib_GetPlayersInRadius_Sort(player1, player2, const clients[], Handle:hndl)
+{
+ return FloatCompare(getPlayersInRadius_distances[player1], getPlayersInRadius_distances[player2]);
+}
+
+/**
+ * Gets the next player observing client starting at start.
+ *
+ * @param client Client Index (Observer Target)
+ * @param start Start Index.
+ * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants).
+ * @return Client Index or -1 if no client was found
+ */
+stock Client_GetNextObserver(client, start=1, flags=CLIENTFILTER_ALL)
+{
+ for (new player=start; player <= MaxClients; player++) {
+
+ if (Client_MatchesFilter(player, CLIENTFILTER_OBSERVERS | flags)) {
+
+ if (Client_GetObserverTarget(player) == client) {
+ return player;
+ }
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * Searchs and returns the game's player_manager entity.
+ * This should be called on every map start.
+ *
+ * @return player_manager entity or INVALID_ENT_REFERENCE if not found.
+ */
+stock Client_GetPlayerManager()
+{
+ static player_manager = INVALID_ENT_REFERENCE;
+
+ if (player_manager != INVALID_ENT_REFERENCE) {
+
+ if (Entity_IsValid(player_manager)) {
+ return player_manager;
+ }
+ else {
+ player_manager = INVALID_ENT_REFERENCE;
+ }
+ }
+
+ new maxEntities = GetMaxEntities();
+
+ for (new entity=0; entity < maxEntities; entity++) {
+
+ if (!Entity_IsValid(entity)) {
+ continue;
+ }
+
+ if (Entity_ClassNameMatches(entity, "player_manager", true)) {
+ player_manager = EntIndexToEntRef(entity);
+
+ return player_manager;
+ }
+ }
+
+ return INVALID_ENT_REFERENCE;
+}
+
+/**
+ * Sets the client's ping as displayed in the scoreboards.
+ * Should be called OnGameFrame.
+ *
+ * @param client Client Index
+ * @param start New ping value.
+ * @return True on sucess, false otherwise.
+ */
+stock Client_SetPing(client, value)
+{
+ new player_manager = Client_GetPlayerManager();
+
+ static offset = -1;
+
+ if (offset== -1) {
+ offset = GetEntSendPropOffs(player_manager, "m_iPing", true);
+
+ if (offset == -1) {
+ return false;
+ }
+ }
+
+ SetEntData(player_manager, offset + (client * 4), value, 4, true);
+
+ return true;
+}
+
+static printToTop_excludeclient = -1;
+
+/**
+ * Exclude a client from the next call to a Client_PrintToTop function.
+ *
+ * @param client Client Index.
+ * @noreturn
+ */
+stock Client_PrintToTopExclude(client)
+{
+ printToTop_excludeclient = client;
+}
+
+/**
+ * Prints colored text to the top left of the screen
+ * for one client. Does not work in all games.
+ * Line Breaks can't be done.
+ *
+ * @param client Client Index.
+ * @param r Red amount.
+ * @param g Green amount.
+ * @param b Blue amount.
+ * @param a Transparency.
+ * @param duration Duration in seconds the text stays (min 10 - max 200 seconds).
+ * @param text Text to print to.
+ * @return True on success, false if the key value for the dialog couldn't be created or closed.
+ */
+stock bool:Client_PrintToTopRaw(client, r=255, g=255, b=255, a=255, Float:duration=10.0, const String:text[])
+{
+ //message line max 50
+ //overline: 39*_
+ //underline: 44*T
+ new Handle:keyValue = CreateKeyValues("Stuff", "title", text);
+
+ if (keyValue == INVALID_HANDLE) {
+ return false;
+ }
+
+ KvSetColor(keyValue, "color", r, g, b, a);
+ KvSetNum(keyValue, "level", 1);
+ KvSetNum(keyValue, "time", RoundToFloor(duration));
+
+ CreateDialog(client, keyValue, DialogType_Msg);
+
+ if (!CloseHandle(keyValue)) {
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Prints colored text to the top left of the screen
+ * for one client. Does not work in all games.
+ * Line Breaks can't be done.
+ *
+ * @param client Client Index.
+ * @param r Red amount.
+ * @param g Green amount.
+ * @param b Blue amount.
+ * @param a Transparency.
+ * @param duration Duration in seconds the text stays (min 10 - max 200 seconds).
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @return True on success, false if the key value for the dialog couldn't be created or closed.
+ */
+stock bool:Client_PrintToTop(client, r=255, g=255, b=255, a=255, Float:duration=10.0, const String:format[], any:...)
+{
+ new String:buffer[150];
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), format, 8);
+
+ return Client_PrintToTopRaw(client, r, g, b, a, duration, buffer);
+}
+
+/**
+ * Prints colored text to the top left of the screen
+ * to all clients. Does not work in all games.
+ * Line Breaks can't be done.
+ *
+ * @param r Red amount.
+ * @param g Green amount.
+ * @param b Blue amount.
+ * @param a Transparency.
+ * @param duration Duration in seconds the text stays (min 10 - max 200 seconds).
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock Client_PrintToTopAll(r=255, g=255, b=255, a=255, Float:duration=10.0, const String:format[], any:...)
+{
+ decl
+ String:buffer[150];
+ new
+ language,
+ lastLanguage = -1;
+
+ for (new client=1; client <= MaxClients; client++) {
+
+ if (!IsClientInGame(client)) {
+ continue;
+ }
+
+ if (client == printToTop_excludeclient) {
+ printToTop_excludeclient = -1;
+ continue;
+ }
+
+ language = GetClientLanguage(client);
+
+ if (language != lastLanguage) {
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), format, 7);
+
+ lastLanguage = language;
+ }
+
+ Client_PrintToTopRaw(client, r, g, b, a, duration, buffer);
+ }
+}
+
+/**
+ * Prints colored text to the top left of the screen
+ * to specified clients. Does not work in all games.
+ * Line Breaks can't be done.
+ *
+ * @param clients Client Array.
+ * @param numClients Number of clients in the clients array.
+ * @param r Red amount.
+ * @param g Green amount.
+ * @param b Blue amount.
+ * @param a Transparency.
+ * @param duration Duration in seconds the text stays (min 10 - max 200 seconds).
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock Client_PrintToTopEx(clients[], numClients, r=255, g=255, b=255, a=255, Float:duration=10.0, const String:format[], any:...)
+{
+ decl
+ String:buffer[150];
+ new
+ client,
+ language,
+ lastLanguage = -1;
+
+ for (new i=0; i < numClients; i++) {
+
+ client = clients[i];
+
+ if (!IsClientInGame(client)) {
+ continue;
+ }
+
+ if (client == printToTop_excludeclient) {
+ printToTop_excludeclient = -1;
+ continue;
+ }
+
+ language = GetClientLanguage(client);
+
+ if (language != lastLanguage) {
+ SetGlobalTransTarget(client);
+ VFormat(buffer, sizeof(buffer), format, 9);
+
+ lastLanguage = language;
+ }
+
+ Client_PrintToTopRaw(client, r, g, b, a, duration, buffer);
+ }
+}
+
+/**
+ * Opens the scoreboard for a specific client
+ *
+ * @tested csgo
+ * @param client Client index
+ * @noreturn
+ */
+stock Client_ShowScoreboard(client, flags=USERMSG_RELIABLE | USERMSG_BLOCKHOOKS)
+{
+ new Handle:handle = StartMessageOne("VGUIMenu", client, flags);
+
+ if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available &&
+ GetUserMessageType() == UM_Protobuf) {
+
+ PbSetString(handle, "name", "scores");
+ PbSetBool(handle, "show", true);
+ }
+ else {
+ BfWriteString(handle, "scores");
+ BfWriteByte(handle, 1); // Show
+ BfWriteByte(handle, 0); // subkeys count
+ }
+
+ EndMessage();
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/colors.inc b/sourcemod-1.5-dev/scripting/include/smlib/colors.inc
new file mode 100644
index 0000000..600f5cc
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/colors.inc
@@ -0,0 +1,528 @@
+#if defined _smlib_colors_included
+ #endinput
+#endif
+#define _smlib_colors_included
+
+#include <sourcemod>
+#include <smlib/arrays>
+#include <smlib/teams>
+
+#define CHATCOLOR_NOSUBJECT -2
+#define SMLIB_COLORS_GAMEDATAFILE "smlib_colors.games"
+
+enum ChatColorSubjectType
+{
+ ChatColorSubjectType_none = -3,
+
+ // Subject/Team colors
+ ChatColorSubjectType_player = -2,
+ ChatColorSubjectType_undefined = -1,
+ ChatColorSubjectType_world = 0
+ // Anything higher is a specific team
+}
+
+enum ChatColorInfo
+{
+ ChatColorInfo_Code,
+ ChatColorInfo_Alternative,
+ bool:ChatColorInfo_Supported,
+ ChatColorSubjectType:ChatColorInfo_SubjectType
+};
+
+enum ChatColor
+{
+ ChatColor_Normal,
+ ChatColor_Orange,
+ ChatColor_Red,
+ ChatColor_RedBlue,
+ ChatColor_Blue,
+ ChatColor_BlueRed,
+ ChatColor_Team,
+ ChatColor_Lightgreen,
+ ChatColor_Gray,
+ ChatColor_Green,
+ ChatColor_Olivegreen,
+ ChatColor_Black
+}
+
+static String:chatColorTags[][] = {
+ "N", // Normal
+ "O", // Orange
+ "R", // Red
+ "RB", // Red, Blue
+ "B", // Blue
+ "BR", // Blue, Red
+ "T", // Team
+ "L", // Light green
+ "GRA", // GRAy
+ "G", // Green
+ "OG", // Olive green
+ "BLA" // BLAck
+};
+
+static String:chatColorNames[][] = {
+ "normal", // Normal
+ "orange", // Orange
+ "red", // Red
+ "redblue", // Red, Blue
+ "blue", // Blue
+ "bluered", // Blue, Red
+ "team", // Team
+ "lightgreen", // Light green
+ "gray", // GRAy
+ "green", // Green
+ "olivegreen", // Olive green
+ "black" // BLAck
+};
+
+static chatColorInfo[][ChatColorInfo] =
+{
+ // Code , alternative , Is Supported? Chat color subject type Color name
+ { '\x01', -1/* None */ , true, ChatColorSubjectType_none, }, // Normal
+ { '\x01', 0 /* None */ , true, ChatColorSubjectType_none, }, // Orange
+ { '\x03', 9 /* Green */ , true, ChatColorSubjectType:2 }, // Red
+ { '\x03', 4 /* Blue */ , true, ChatColorSubjectType:2 }, // Red, Blue
+ { '\x03', 9 /* Green */ , true, ChatColorSubjectType:3 }, // Blue
+ { '\x03', 2 /* Red */ , true, ChatColorSubjectType:3 }, // Blue, Red
+ { '\x03', 9 /* Green */ , true, ChatColorSubjectType_player }, // Team
+ { '\x03', 9 /* Green */ , true, ChatColorSubjectType_world }, // Light green
+ { '\x03', 9 /* Green */ , true, ChatColorSubjectType_undefined},// GRAy
+ { '\x04', 0 /* Normal*/ , true, ChatColorSubjectType_none }, // Green
+ { '\x05', 9 /* Green */ , true, ChatColorSubjectType_none }, // Olive green
+ { '\x06', 9 /* Green */ , true, ChatColorSubjectType_none } // BLAck
+};
+
+static bool:checkTeamPlay = false;
+static Handle:mp_teamplay = INVALID_HANDLE;
+static bool:isSayText2_supported = true;
+static chatSubject = CHATCOLOR_NOSUBJECT;
+
+/**
+ * Sets the subject (a client) for the chat color parser.
+ * Call this before Color_ParseChatText() or Client_PrintToChat().
+ *
+ * @param client Client Index/Subject
+ * @noreturn
+ */
+stock Color_ChatSetSubject(client)
+{
+ chatSubject = client;
+}
+
+/**
+ * Gets the subject used for the chat color parser.
+ *
+ * @return Client Index/Subject, or CHATCOLOR_NOSUBJECT if none
+ */
+stock Color_ChatGetSubject()
+{
+ return chatSubject;
+}
+
+/**
+ * Clears the subject used for the chat color parser.
+ * Call this after Color_ParseChatText().
+ *
+ * @noreturn
+ */
+stock Color_ChatClearSubject()
+{
+ chatSubject = CHATCOLOR_NOSUBJECT;
+}
+
+/**
+ * Parses a chat string and converts all color tags to color codes.
+ * This is a very powerful function that works recursively over the color information
+ * table. The support colors are hardcoded, but can be overriden for each game by
+ * creating the file gamedata/smlib_colors.games.txt.
+ *
+ * @param str Chat String
+ * @param subject Output Buffer
+ * @param size Output Buffer size
+ * @return Returns a value for the subject
+ */
+stock Color_ParseChatText(const String:str[], String:buffer[], size)
+{
+ new
+ bool:inBracket = false,
+ x = 0, x_buf = 0, x_tag = 0,
+ subject = CHATCOLOR_NOSUBJECT;
+
+ decl
+ String:sTag[10] = "", // This should be able to hold "\x08RRGGBBAA"\0
+ String:colorCode[10] = "", // This should be able to hold "\x08RRGGBBAA"\0
+ String:currentColor[10] = "\x01"; // Initialize with normal color
+
+ size--;
+
+ // Every chat message has to start with a
+ // color code, otherwise it will ignore all colors.
+ buffer[x_buf++] = '\x01';
+
+ while (str[x] != '\0') {
+
+ if (size == x_buf) {
+ break;
+ }
+
+ new character = str[x++];
+
+ if (inBracket) {
+ // We allow up to 9 characters in the tag (#RRGGBBAA)
+ if (character == '}' || x_tag > 9) {
+ inBracket = false;
+ sTag[x_tag] = '\0';
+ x_tag = 0;
+
+ if (character == '}') {
+ Color_TagToCode(sTag, subject, colorCode);
+
+ if (colorCode[0] == '\0') {
+ // We got an unknown tag, ignore this
+ // and forward it to the buffer.
+
+ // Terminate buffer with \0 so Format can handle it.
+ buffer[x_buf] = '\0';
+ x_buf = Format(buffer, size, "%s{%s}", buffer, sTag);
+
+ // We 'r done here
+ continue;
+ }
+ else if (!StrEqual(colorCode, currentColor)) {
+ // If we are already using this color,
+ // we don't need to set it again.
+
+ // Write the color code to our buffer.
+ // x_buf will be increased by the number of cells written.
+ x_buf += strcopy(buffer[x_buf], size - x_buf, colorCode);
+
+ // Remember the current color.
+ strcopy(currentColor, sizeof(currentColor), colorCode);
+ }
+ }
+ else {
+ // If the tag character limit exceeds 9,
+ // we have to do something.
+
+ // Terminate buffer with \0 so Format can handle it.
+ buffer[x_buf] = '\0';
+ x_buf = Format(buffer, size, "%s{%s%c", buffer, sTag, character);
+ }
+ }
+ else if (character == '{' && !x_tag) {
+ buffer[x_buf++] = '{';
+ inBracket = false;
+ }
+ else {
+ sTag[x_tag++] = character;
+ }
+ }
+ else if (character == '{') {
+ inBracket = true;
+ }
+ else {
+ buffer[x_buf++] = character;
+ }
+ }
+
+ // Write remaining text to the buffer,
+ // if we have been inside brackets.
+ if (inBracket) {
+ buffer[x_buf] = '\0';
+ x_buf = Format(buffer, size, "%s{%s", buffer, sTag);
+ }
+
+ buffer[x_buf] = '\0';
+
+ return subject;
+}
+
+/**
+ * Converts a chat color tag to its code character.
+ *
+ * @param tag Color Tag String.
+ * @param subject Subject variable to pass
+ * @param result The result as character sequence (string). This will be \0 if the tag is unkown.
+ * @noreturn
+ */
+stock Color_TagToCode(const String:tag[], &subject=-1, String:result[10])
+{
+ // Check if the tag starts with a '#'.
+ // We will handle it has RGB(A)-color code then.
+ if (tag[0] == '#') {
+ new length_tag = strlen(tag);
+ switch (length_tag - 1) {
+ // #RGB -> \07RRGGBB
+ case 3: {
+ FormatEx(
+ result, sizeof(result), "\x07%c%c%c%c%c%c",
+ tag[1], tag[1], tag[2], tag[2], tag[3], tag[3]
+ );
+ }
+ // #RGBA -> \08RRGGBBAA
+ case 4: {
+ FormatEx(
+ result, sizeof(result), "\x08%c%c%c%c%c%c%c%c",
+ tag[1], tag[1], tag[2], tag[2], tag[3], tag[3], tag[4], tag[4]
+ );
+ }
+ // #RRGGBB -> \07RRGGBB
+ case 6: {
+ FormatEx(result, sizeof(result), "\x07%s", tag[1]);
+ }
+ // #RRGGBBAA -> \08RRGGBBAA
+ case 8: {
+ FormatEx(result, sizeof(result), "\x08%s", tag[1]);
+ }
+ default: {
+ result[0] = '\0';
+ }
+ }
+
+ return;
+ }
+ else {
+ // Try to handle this string as color name
+ new n = Array_FindString(chatColorTags, sizeof(chatColorTags), tag);
+
+ // Check if this tag is invalid
+ if (n == -1) {
+ result[0] = '\0';
+ return;
+ }
+
+ // Check if the color is actually supported 'n stuff.
+ Color_GetChatColorInfo(n, subject);
+
+ result[0] = chatColorInfo[n][ChatColorInfo_Code];
+ result[1] = '\0';
+ }
+
+ return;
+}
+
+/**
+ * Strips all color control characters in a string.
+ * The Output buffer can be the same as the input buffer.
+ * Original code by Psychonic, thanks.
+ *
+ * @param input Input String.
+ * @param output Output String.
+ * @param size Max Size of the Output string
+ * @noreturn
+ */
+stock Color_StripFromChatText(const String:input[], String:output[], size)
+{
+ new x = 0;
+ for (new i=0; input[i] != '\0'; i++) {
+
+ if (x+1 == size) {
+ break;
+ }
+
+ new character = input[i];
+
+ if (character > 0x08) {
+ output[x++] = character;
+ }
+ }
+
+ output[x] = '\0';
+}
+
+/**
+ * Checks the gamename and sets default values.
+ * For example if some colors are supported, or
+ * if a game uses another color code for a specific color.
+ * All those hardcoded default values can be overriden in
+ * smlib's color gamedata file.
+ *
+ * @noreturn
+ */
+static stock Color_ChatInitialize()
+{
+ static initialized = false;
+
+ if (initialized) {
+ return;
+ }
+
+ initialized = true;
+
+ decl String:gameFolderName[32];
+ GetGameFolderName(gameFolderName, sizeof(gameFolderName));
+
+ chatColorInfo[ChatColor_Black][ChatColorInfo_Supported] = false;
+
+ if (strncmp(gameFolderName, "left4dead", 9, false) != 0 &&
+ !StrEqual(gameFolderName, "cstrike", false) &&
+ !StrEqual(gameFolderName, "tf", false))
+ {
+ chatColorInfo[ChatColor_Lightgreen][ChatColorInfo_Supported]= false;
+ chatColorInfo[ChatColor_Gray][ChatColorInfo_Supported] = false;
+ }
+
+ if (StrEqual(gameFolderName, "tf", false)) {
+ chatColorInfo[ChatColor_Black][ChatColorInfo_Supported] = true;
+
+ chatColorInfo[ChatColor_Gray][ChatColorInfo_Code] = '\x01';
+ chatColorInfo[ChatColor_Gray][ChatColorInfo_SubjectType] = ChatColorSubjectType_none;
+ }
+ else if (strncmp(gameFolderName, "left4dead", 9, false) == 0) {
+ chatColorInfo[ChatColor_Red][ChatColorInfo_SubjectType] = ChatColorSubjectType:3;
+ chatColorInfo[ChatColor_RedBlue][ChatColorInfo_SubjectType] = ChatColorSubjectType:3;
+ chatColorInfo[ChatColor_Blue][ChatColorInfo_SubjectType] = ChatColorSubjectType:2;
+ chatColorInfo[ChatColor_BlueRed][ChatColorInfo_SubjectType] = ChatColorSubjectType:2;
+
+ chatColorInfo[ChatColor_Orange][ChatColorInfo_Code] = '\x04';
+ chatColorInfo[ChatColor_Green][ChatColorInfo_Code] = '\x05';
+ }
+ else if (StrEqual(gameFolderName, "hl2mp", false)) {
+ chatColorInfo[ChatColor_Red][ChatColorInfo_SubjectType] = ChatColorSubjectType:3;
+ chatColorInfo[ChatColor_RedBlue][ChatColorInfo_SubjectType] = ChatColorSubjectType:3;
+ chatColorInfo[ChatColor_Blue][ChatColorInfo_SubjectType] = ChatColorSubjectType:2;
+ chatColorInfo[ChatColor_BlueRed][ChatColorInfo_SubjectType] = ChatColorSubjectType:2;
+ chatColorInfo[ChatColor_Black][ChatColorInfo_Supported] = true;
+
+ checkTeamPlay = true;
+ }
+ else if (StrEqual(gameFolderName, "dod", false)) {
+ chatColorInfo[ChatColor_Gray][ChatColorInfo_Code] = '\x01';
+ chatColorInfo[ChatColor_Gray][ChatColorInfo_SubjectType] = ChatColorSubjectType_none;
+
+ chatColorInfo[ChatColor_Black][ChatColorInfo_Supported] = true;
+ chatColorInfo[ChatColor_Orange][ChatColorInfo_Supported] = false;
+ }
+
+ if (GetUserMessageId("SayText2") == INVALID_MESSAGE_ID) {
+ isSayText2_supported = false;
+ }
+
+ decl String:path_gamedata[PLATFORM_MAX_PATH];
+ BuildPath(Path_SM, path_gamedata, sizeof(path_gamedata), "gamedata/%s.txt", SMLIB_COLORS_GAMEDATAFILE);
+
+ if (FileExists(path_gamedata)) {
+ new Handle:gamedata = INVALID_HANDLE;
+
+ if ((gamedata = LoadGameConfigFile(SMLIB_COLORS_GAMEDATAFILE)) != INVALID_HANDLE) {
+
+ decl String:keyName[32], String:buffer[6];
+
+ for (new i=0; i < sizeof(chatColorNames); i++) {
+
+ Format(keyName, sizeof(keyName), "%s_code", chatColorNames[i]);
+ if (GameConfGetKeyValue(gamedata, keyName, buffer, sizeof(buffer))) {
+ chatColorInfo[i][ChatColorInfo_Code] = StringToInt(buffer);
+ }
+
+ Format(keyName, sizeof(keyName), "%s_alternative", chatColorNames[i]);
+ if (GameConfGetKeyValue(gamedata, keyName, buffer, sizeof(buffer))) {
+ chatColorInfo[i][ChatColorInfo_Alternative] = buffer[0];
+ }
+
+ Format(keyName, sizeof(keyName), "%s_supported", chatColorNames[i]);
+ if (GameConfGetKeyValue(gamedata, keyName, buffer, sizeof(buffer))) {
+ chatColorInfo[i][ChatColorInfo_Supported] = StrEqual(buffer, "true");
+ }
+
+ Format(keyName, sizeof(keyName), "%s_subjecttype", chatColorNames[i]);
+ if (GameConfGetKeyValue(gamedata, keyName, buffer, sizeof(buffer))) {
+ chatColorInfo[i][ChatColorInfo_SubjectType] = ChatColorSubjectType:StringToInt(buffer);
+ }
+ }
+
+ if (GameConfGetKeyValue(gamedata, "checkteamplay", buffer, sizeof(buffer))) {
+ checkTeamPlay = StrEqual(buffer, "true");
+ }
+
+ CloseHandle(gamedata);
+ }
+ }
+
+ mp_teamplay = FindConVar("mp_teamplay");
+}
+
+/**
+ * Checks if the passed color index is actually supported
+ * for the current game. If not, the index will be overwritten
+ * The color resolving works recursively until a valid color is found.
+ *
+ * @param index
+ * @param subject A client index or CHATCOLOR_NOSUBJECT
+ * @noreturn
+ */
+static stock Color_GetChatColorInfo(&index, &subject=CHATCOLOR_NOSUBJECT)
+{
+ Color_ChatInitialize();
+
+ if (index == -1) {
+ index = 0;
+ }
+
+ while (!chatColorInfo[index][ChatColorInfo_Supported]) {
+
+ new alternative = chatColorInfo[index][ChatColorInfo_Alternative];
+
+ if (alternative == -1) {
+ index = 0;
+ break;
+ }
+
+ index = alternative;
+ }
+
+ if (index == -1) {
+ index = 0;
+ }
+
+ new newSubject = CHATCOLOR_NOSUBJECT;
+ new ChatColorSubjectType:type = chatColorInfo[index][ChatColorInfo_SubjectType];
+
+ switch (type) {
+
+ case ChatColorSubjectType_none: {
+ }
+ case ChatColorSubjectType_player: {
+ newSubject = chatSubject;
+ }
+ case ChatColorSubjectType_undefined: {
+ newSubject = -1;
+ }
+ case ChatColorSubjectType_world: {
+ newSubject = 0;
+ }
+ default: {
+
+ if (!checkTeamPlay || GetConVarBool(mp_teamplay)) {
+
+ if (subject > 0 && subject <= MaxClients) {
+
+ if (GetClientTeam(subject) == _:type) {
+ newSubject = subject;
+ }
+ }
+ else if (subject == CHATCOLOR_NOSUBJECT) {
+ new client = Team_GetAnyClient(_:type);
+
+ if (client != -1) {
+ newSubject = client;
+ }
+ }
+ }
+ }
+ }
+
+ if (type > ChatColorSubjectType_none &&
+ ((subject != CHATCOLOR_NOSUBJECT && subject != newSubject) || newSubject == CHATCOLOR_NOSUBJECT || !isSayText2_supported))
+ {
+ index = chatColorInfo[index][ChatColorInfo_Alternative];
+ newSubject = Color_GetChatColorInfo(index, subject);
+ }
+
+ // Only set the subject if there is no subject set already.
+ if (subject == CHATCOLOR_NOSUBJECT) {
+ subject = newSubject;
+ }
+
+ return newSubject;
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/concommands.inc b/sourcemod-1.5-dev/scripting/include/smlib/concommands.inc
new file mode 100644
index 0000000..a90fd1c
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/concommands.inc
@@ -0,0 +1,47 @@
+#if defined _smlib_concommands_included
+ #endinput
+#endif
+#define _smlib_concommands_included
+
+#include <sourcemod>
+#include <smlib/clients>
+
+/**
+ * Checks if a ConCommand has one or more flags set.
+ *
+ * @param command ConCommand name.
+ * @param flags Flags to check.
+ * @return True if flags are set, false otherwise.
+ */
+stock bool:ConCommand_HasFlags(const String:command[], const flags)
+{
+ return bool:(GetCommandFlags(command) & flags);
+}
+
+/**
+ * Adds one or more flags to a ConCommand.
+ *
+ * @param command ConCommand name.
+ * @param flags Flags to add.
+ * @noreturn
+ */
+stock ConCommand_AddFlags(const String:command[], const flags)
+{
+ new newFlags = GetCommandFlags(command);
+ newFlags |= flags;
+ SetCommandFlags(command, newFlags);
+}
+
+/**
+ * Removes one ore more flags from a ConCommand.
+ *
+ * @param command ConCommand name.
+ * @param flags Flags to remove
+ * @noreturn
+ */
+stock ConCommand_RemoveFlags(const String:command[], const flags)
+{
+ new newFlags = GetCommandFlags(command);
+ newFlags &= ~flags;
+ SetCommandFlags(command, newFlags);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/convars.inc b/sourcemod-1.5-dev/scripting/include/smlib/convars.inc
new file mode 100644
index 0000000..95c40cd
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/convars.inc
@@ -0,0 +1,72 @@
+#if defined _smlib_convars_included
+ #endinput
+#endif
+#define _smlib_convars_included
+
+#include <sourcemod>
+
+/**
+ * Checks if a ConVar has one or more flags set.
+ *
+ * @param convar ConVar Handle.
+ * @param flags Flags to check.
+ * @return True if flags are set, false otherwise.
+ */
+stock bool:Convar_HasFlags(Handle:convar, flags)
+{
+ return bool:(GetConVarFlags(convar) & flags);
+}
+
+/**
+ * Adds one or more flags to a ConVar.
+ *
+ * @param convar ConVar Handle.
+ * @param flags Flags to add.
+ * @noreturn
+ */
+stock Convar_AddFlags(Handle:convar, flags)
+{
+ new newFlags = GetConVarFlags(convar);
+ newFlags |= flags;
+ SetConVarFlags(convar, newFlags);
+}
+
+/**
+ * Removes one ore more flags from a ConVar.
+ *
+ * @param convar ConVar Handle.
+ * @param flags Flags to remove
+ * @noreturn
+ */
+stock Convar_RemoveFlags(Handle:convar, flags)
+{
+ new newFlags = GetConVarFlags(convar);
+ newFlags &= ~flags;
+ SetConVarFlags(convar, newFlags);
+}
+
+/**
+ * Checks if a String is a valid ConVar or
+ * Console Command name.
+ *
+ * @param name String Name.
+ * @return True if the name specified is a valid ConVar or console command name, false otherwise.
+ */
+stock bool:Convar_IsValidName(const String:name[])
+{
+ if (name[0] == '\0') {
+ return false;
+ }
+
+ new n=0;
+ while (name[n] != '\0') {
+
+ if (!IsValidConVarChar(name[n])) {
+ return false;
+ }
+
+ n++;
+ }
+
+ return true;
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/crypt.inc b/sourcemod-1.5-dev/scripting/include/smlib/crypt.inc
new file mode 100644
index 0000000..982b47f
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/crypt.inc
@@ -0,0 +1,630 @@
+#if defined _smlib_crypt_included
+ #endinput
+#endif
+#define _smlib_crypt_included
+
+#include <sourcemod>
+
+/**********************************************************************************
+ *
+ * Base64 Encoding/Decoding Functions
+ * All Credits to to SirLamer & ScriptCoderPro
+ * Taken from http://forums.alliedmods.net/showthread.php?t=101764
+ *
+ ***********************************************************************************/
+
+// The Base64 encoding table
+static const String:base64_sTable[] =
+ // 0000000000111111111122222222223333333333444444444455555555556666
+ // 0123456789012345678901234567890123456789012345678901234567890123
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+// The Base64 decoding table
+static const base64_decodeTable[] = {
+// 0 1 2 3 4 5 6 7 8 9
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 9
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10 - 19
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 - 29
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 30 - 39
+ 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, // 40 - 49
+ 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, // 50 - 59
+ 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, // 60 - 69
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 70 - 79
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 80 - 89
+ 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, // 90 - 99
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // 100 - 109
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // 110 - 119
+ 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, // 120 - 129
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 130 - 139
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 140 - 149
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 150 - 159
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160 - 169
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 170 - 179
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 180 - 189
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 190 - 199
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 200 - 209
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 210 - 219
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 220 - 229
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 230 - 239
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240 - 249
+ 0, 0, 0, 0, 0, 0 // 250 - 256
+};
+
+/*
+ * For some reason the standard demands a string in 24-bit (3 character) intervals.
+ * This fill character is used to identify unused bytes at the end of the string.
+ */
+static const base64_cFillChar = '=';
+
+// The conversion characters between the standard and URL-compliance Base64 protocols
+static const String:base64_mime_chars[] = "+/=";
+static const String:base64_url_chars[] = "-_.";
+
+/*
+ * Encodes a string or binary data into Base64
+ *
+ * @param sString The input string or binary data to be encoded.
+ * @param sResult The storage buffer for the Base64-encoded result.
+ * @param len The maximum length of the storage buffer, in characters/bytes.
+ * @param sourcelen (optional): The number of characters or length in bytes to be read from the input source.
+ * This is not needed for a text string, but is important for binary data since there is no end-of-line character.
+ * @return The length of the written Base64 string, in bytes.
+ */
+stock Crypt_Base64Encode(const String:sString[], String:sResult[], len, sourcelen=0)
+{
+ new nLength; // The string length to be read from the input
+ new resPos; // The string position in the result buffer
+
+ // If the read length was specified, use it; otherwise, pull the string length from the input.
+ if (sourcelen > 0) {
+ nLength = sourcelen;
+ }
+ else {
+ nLength = strlen(sString);
+ }
+
+ // Loop through and generate the Base64 encoded string
+ // NOTE: This performs the standard encoding process. Do not manipulate the logic within this loop.
+ for (new nPos = 0; nPos < nLength; nPos++) {
+ new cCode;
+
+ cCode = (sString[nPos] >> 2) & 0x3f;
+
+ resPos += FormatEx(sResult[resPos], len - resPos, "%c", base64_sTable[cCode]);
+
+ cCode = (sString[nPos] << 4) & 0x3f;
+ if (++nPos < nLength) {
+ cCode |= (sString[nPos] >> 4) & 0x0f;
+ }
+ resPos += FormatEx(sResult[resPos], len - resPos, "%c", base64_sTable[cCode]);
+
+ if ( nPos < nLength ) {
+ cCode = (sString[nPos] << 2) & 0x3f;
+ if (++nPos < nLength) {
+ cCode |= (sString[nPos] >> 6) & 0x03;
+ }
+
+ resPos += FormatEx(sResult[resPos], len - resPos, "%c", base64_sTable[cCode]);
+ }
+ else {
+ nPos++;
+ resPos += FormatEx(sResult[resPos], len - resPos, "%c", base64_cFillChar);
+ }
+
+ if (nPos < nLength) {
+ cCode = sString[nPos] & 0x3f;
+ resPos += FormatEx(sResult[resPos], len - resPos, "%c", base64_sTable[cCode]);
+ }
+ else {
+ resPos += FormatEx(sResult[resPos], len - resPos, "%c", base64_cFillChar);
+ }
+ }
+
+ return resPos;
+}
+
+
+/*
+ * Decodes a Base64 string.
+ *
+ * @param sString The input string in compliant Base64 format to be decoded.
+ * @param sResult The storage buffer for the decoded text strihg or binary data.
+ * @param len The maximum length of the storage buffer, in characters/bytes.
+ * @return The length of the decoded data, in bytes.
+ */
+stock Crypt_Base64Decode(const String:sString[], String:sResult[], len)
+{
+ new nLength = strlen(sString); // The string length to be read from the input
+ new resPos; // The string position in the result buffer
+
+ // Loop through and generate the Base64 encoded string
+ // NOTE: This performs the standard encoding process. Do not manipulate the logic within this loop.
+ for (new nPos = 0; nPos < nLength; nPos++) {
+
+ new c, c1;
+
+ c = base64_decodeTable[sString[nPos++]];
+ c1 = base64_decodeTable[sString[nPos]];
+
+ c = (c << 2) | ((c1 >> 4) & 0x3);
+
+ resPos += FormatEx(sResult[resPos], len - resPos, "%c", c);
+
+ if (++nPos < nLength) {
+
+ c = sString[nPos];
+
+ if (c == base64_cFillChar)
+ break;
+
+ c = base64_decodeTable[sString[nPos]];
+ c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
+
+ resPos += FormatEx(sResult[resPos], len - resPos, "%c", c1);
+ }
+
+ if (++nPos < nLength) {
+
+ c1 = sString[nPos];
+
+ if (c1 == base64_cFillChar)
+ break;
+
+ c1 = base64_decodeTable[sString[nPos]];
+ c = ((c << 6) & 0xc0) | c1;
+
+ resPos += FormatEx(sResult[resPos], len - resPos, "%c", c);
+ }
+ }
+
+ return resPos;
+}
+
+
+/*
+ * Converts a standards-compliant Base64 string to the commonly accepted URL-compliant alternative.
+ * Note: The result will be the same length as the input string as long as the output buffer is large enough.
+ *
+ * @param sString The standards-compliant Base64 input string to converted.
+ * @param sResult The storage buffer for the URL-compliant result.
+ * @param len The maximum length of the storage buffer in characters/bytes.
+ * @return Number of cells written.
+ */
+stock Crypt_Base64MimeToUrl(const String:sString[], String:sResult[], len)
+{
+ new chars_len = sizeof(base64_mime_chars); // Length of the two standards vs. URL character lists
+ new nLength; // The string length to be read from the input
+ new temp_char; // Buffer character
+
+ nLength = strlen(sString);
+
+ new String:sTemp[nLength+1]; // Buffer string
+
+ // Loop through string
+ for (new i = 0; i < nLength; i++) {
+ temp_char = sString[i];
+
+ for (new j = 0; j < chars_len; j++) {
+
+ if(temp_char == base64_mime_chars[j]) {
+ temp_char = base64_url_chars[j];
+ break;
+ }
+ }
+
+ sTemp[i] = temp_char;
+ }
+
+ sTemp[nLength] = '\0';
+
+ return strcopy(sResult, len, sTemp);
+}
+
+/*
+ * Base64UrlToMime(String:sResult[], len, const String:sString[], sourcelen)
+ * Converts a URL-compliant Base64 string to the standards-compliant version.
+ * Note: The result will be the same length as the input string as long as the output buffer is large enough.
+ *
+ * @param sString The URL-compliant Base64 input string to converted.
+ * @param sResult The storage buffer for the standards-compliant result.
+ * @param len The maximum length of the storage buffer in characters/bytes.
+ * @return Number of cells written.
+ */
+stock Crypt_Base64UrlToMime(const String:sString[], String:sResult[], len)
+{
+ new chars_len = sizeof(base64_mime_chars); // Length of the two standards vs. URL character lists
+ new nLength; // The string length to be read from the input
+ new temp_char; // Buffer character
+
+ nLength = strlen(sString);
+
+ new String:sTemp[nLength+1]; // Buffer string
+
+ // Loop through string
+ for (new i = 0; i < nLength; i++) {
+ temp_char = sString[i];
+ for (new j = 0; j < chars_len; j++) {
+ if (temp_char == base64_url_chars[j]) {
+ temp_char = base64_mime_chars[j];
+ break;
+ }
+ }
+
+ sTemp[i] = temp_char;
+ }
+
+ sTemp[nLength] = '\0';
+
+ return strcopy(sResult, len, sTemp);
+}
+
+/**********************************************************************************
+ *
+ * MD5 Encoding Functions
+ * All Credits go to sslice
+ * RSA Data Security, Inc. MD5 Message Digest Algorithm
+ * Taken from http://forums.alliedmods.net/showthread.php?t=67683
+ *
+ ***********************************************************************************/
+
+/*
+ * Calculate the md5 hash of a string.
+ *
+ * @param str Input String
+ * @param output Output String Buffer
+ * @param maxlen Size of the Output String Buffer
+ * @noreturn
+ */
+stock Crypt_MD5(const String:str[], String:output[], maxlen)
+{
+ decl x[2];
+ decl buf[4];
+ decl input[64];
+ new i, ii;
+
+ new len = strlen(str);
+
+ // MD5Init
+ x[0] = x[1] = 0;
+ buf[0] = 0x67452301;
+ buf[1] = 0xefcdab89;
+ buf[2] = 0x98badcfe;
+ buf[3] = 0x10325476;
+
+ // MD5Update
+ new update[16];
+
+ update[14] = x[0];
+ update[15] = x[1];
+
+ new mdi = (x[0] >>> 3) & 0x3F;
+
+ if ((x[0] + (len << 3)) < x[0]) {
+ x[1] += 1;
+ }
+
+ x[0] += len << 3;
+ x[1] += len >>> 29;
+
+ new c = 0;
+ while (len--) {
+ input[mdi] = str[c];
+ mdi += 1;
+ c += 1;
+
+ if (mdi == 0x40) {
+
+ for (i = 0, ii = 0; i < 16; ++i, ii += 4)
+ {
+ update[i] = (input[ii + 3] << 24) | (input[ii + 2] << 16) | (input[ii + 1] << 8) | input[ii];
+ }
+
+ // Transform
+ MD5Transform(buf, update);
+
+ mdi = 0;
+ }
+ }
+
+ // MD5Final
+ new padding[64] = {
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ new inx[16];
+ inx[14] = x[0];
+ inx[15] = x[1];
+
+ mdi = (x[0] >>> 3) & 0x3F;
+
+ len = (mdi < 56) ? (56 - mdi) : (120 - mdi);
+ update[14] = x[0];
+ update[15] = x[1];
+
+ mdi = (x[0] >>> 3) & 0x3F;
+
+ if ((x[0] + (len << 3)) < x[0]) {
+ x[1] += 1;
+ }
+
+ x[0] += len << 3;
+ x[1] += len >>> 29;
+
+ c = 0;
+ while (len--) {
+ input[mdi] = padding[c];
+ mdi += 1;
+ c += 1;
+
+ if (mdi == 0x40) {
+
+ for (i = 0, ii = 0; i < 16; ++i, ii += 4) {
+ update[i] = (input[ii + 3] << 24) | (input[ii + 2] << 16) | (input[ii + 1] << 8) | input[ii];
+ }
+
+ // Transform
+ MD5Transform(buf, update);
+
+ mdi = 0;
+ }
+ }
+
+ for (i = 0, ii = 0; i < 14; ++i, ii += 4) {
+ inx[i] = (input[ii + 3] << 24) | (input[ii + 2] << 16) | (input[ii + 1] << 8) | input[ii];
+ }
+
+ MD5Transform(buf, inx);
+
+ new digest[16];
+ for (i = 0, ii = 0; i < 4; ++i, ii += 4) {
+ digest[ii] = (buf[i]) & 0xFF;
+ digest[ii + 1] = (buf[i] >>> 8) & 0xFF;
+ digest[ii + 2] = (buf[i] >>> 16) & 0xFF;
+ digest[ii + 3] = (buf[i] >>> 24) & 0xFF;
+ }
+
+ FormatEx(output, maxlen, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7],
+ digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]);
+}
+
+static stock MD5Transform_FF(&a, &b, &c, &d, x, s, ac)
+ {
+ a += (((b) & (c)) | ((~b) & (d))) + x + ac;
+ a = (((a) << (s)) | ((a) >>> (32-(s))));
+ a += b;
+}
+
+static stock MD5Transform_GG(&a, &b, &c, &d, x, s, ac)
+ {
+ a += (((b) & (d)) | ((c) & (~d))) + x + ac;
+ a = (((a) << (s)) | ((a) >>> (32-(s))));
+ a += b;
+}
+
+static stock MD5Transform_HH(&a, &b, &c, &d, x, s, ac)
+ {
+ a += ((b) ^ (c) ^ (d)) + x + ac;
+ a = (((a) << (s)) | ((a) >>> (32-(s))));
+ a += b;
+}
+
+static stock MD5Transform_II(&a, &b, &c, &d, x, s, ac)
+{
+ a += ((c) ^ ((b) | (~d))) + x + ac;
+ a = (((a) << (s)) | ((a) >>> (32-(s))));
+ a += b;
+}
+
+static stock MD5Transform(buf[], input[])
+{
+ new a = buf[0];
+ new b = buf[1];
+ new c = buf[2];
+ new d = buf[3];
+
+ MD5Transform_FF(a, b, c, d, input[0], 7, 0xd76aa478);
+ MD5Transform_FF(d, a, b, c, input[1], 12, 0xe8c7b756);
+ MD5Transform_FF(c, d, a, b, input[2], 17, 0x242070db);
+ MD5Transform_FF(b, c, d, a, input[3], 22, 0xc1bdceee);
+ MD5Transform_FF(a, b, c, d, input[4], 7, 0xf57c0faf);
+ MD5Transform_FF(d, a, b, c, input[5], 12, 0x4787c62a);
+ MD5Transform_FF(c, d, a, b, input[6], 17, 0xa8304613);
+ MD5Transform_FF(b, c, d, a, input[7], 22, 0xfd469501);
+ MD5Transform_FF(a, b, c, d, input[8], 7, 0x698098d8);
+ MD5Transform_FF(d, a, b, c, input[9], 12, 0x8b44f7af);
+ MD5Transform_FF(c, d, a, b, input[10], 17, 0xffff5bb1);
+ MD5Transform_FF(b, c, d, a, input[11], 22, 0x895cd7be);
+ MD5Transform_FF(a, b, c, d, input[12], 7, 0x6b901122);
+ MD5Transform_FF(d, a, b, c, input[13], 12, 0xfd987193);
+ MD5Transform_FF(c, d, a, b, input[14], 17, 0xa679438e);
+ MD5Transform_FF(b, c, d, a, input[15], 22, 0x49b40821);
+
+ MD5Transform_GG(a, b, c, d, input[1], 5, 0xf61e2562);
+ MD5Transform_GG(d, a, b, c, input[6], 9, 0xc040b340);
+ MD5Transform_GG(c, d, a, b, input[11], 14, 0x265e5a51);
+ MD5Transform_GG(b, c, d, a, input[0], 20, 0xe9b6c7aa);
+ MD5Transform_GG(a, b, c, d, input[5], 5, 0xd62f105d);
+ MD5Transform_GG(d, a, b, c, input[10], 9, 0x02441453);
+ MD5Transform_GG(c, d, a, b, input[15], 14, 0xd8a1e681);
+ MD5Transform_GG(b, c, d, a, input[4], 20, 0xe7d3fbc8);
+ MD5Transform_GG(a, b, c, d, input[9], 5, 0x21e1cde6);
+ MD5Transform_GG(d, a, b, c, input[14], 9, 0xc33707d6);
+ MD5Transform_GG(c, d, a, b, input[3], 14, 0xf4d50d87);
+ MD5Transform_GG(b, c, d, a, input[8], 20, 0x455a14ed);
+ MD5Transform_GG(a, b, c, d, input[13], 5, 0xa9e3e905);
+ MD5Transform_GG(d, a, b, c, input[2], 9, 0xfcefa3f8);
+ MD5Transform_GG(c, d, a, b, input[7], 14, 0x676f02d9);
+ MD5Transform_GG(b, c, d, a, input[12], 20, 0x8d2a4c8a);
+
+ MD5Transform_HH(a, b, c, d, input[5], 4, 0xfffa3942);
+ MD5Transform_HH(d, a, b, c, input[8], 11, 0x8771f681);
+ MD5Transform_HH(c, d, a, b, input[11], 16, 0x6d9d6122);
+ MD5Transform_HH(b, c, d, a, input[14], 23, 0xfde5380c);
+ MD5Transform_HH(a, b, c, d, input[1], 4, 0xa4beea44);
+ MD5Transform_HH(d, a, b, c, input[4], 11, 0x4bdecfa9);
+ MD5Transform_HH(c, d, a, b, input[7], 16, 0xf6bb4b60);
+ MD5Transform_HH(b, c, d, a, input[10], 23, 0xbebfbc70);
+ MD5Transform_HH(a, b, c, d, input[13], 4, 0x289b7ec6);
+ MD5Transform_HH(d, a, b, c, input[0], 11, 0xeaa127fa);
+ MD5Transform_HH(c, d, a, b, input[3], 16, 0xd4ef3085);
+ MD5Transform_HH(b, c, d, a, input[6], 23, 0x04881d05);
+ MD5Transform_HH(a, b, c, d, input[9], 4, 0xd9d4d039);
+ MD5Transform_HH(d, a, b, c, input[12], 11, 0xe6db99e5);
+ MD5Transform_HH(c, d, a, b, input[15], 16, 0x1fa27cf8);
+ MD5Transform_HH(b, c, d, a, input[2], 23, 0xc4ac5665);
+
+ MD5Transform_II(a, b, c, d, input[0], 6, 0xf4292244);
+ MD5Transform_II(d, a, b, c, input[7], 10, 0x432aff97);
+ MD5Transform_II(c, d, a, b, input[14], 15, 0xab9423a7);
+ MD5Transform_II(b, c, d, a, input[5], 21, 0xfc93a039);
+ MD5Transform_II(a, b, c, d, input[12], 6, 0x655b59c3);
+ MD5Transform_II(d, a, b, c, input[3], 10, 0x8f0ccc92);
+ MD5Transform_II(c, d, a, b, input[10], 15, 0xffeff47d);
+ MD5Transform_II(b, c, d, a, input[1], 21, 0x85845dd1);
+ MD5Transform_II(a, b, c, d, input[8], 6, 0x6fa87e4f);
+ MD5Transform_II(d, a, b, c, input[15], 10, 0xfe2ce6e0);
+ MD5Transform_II(c, d, a, b, input[6], 15, 0xa3014314);
+ MD5Transform_II(b, c, d, a, input[13], 21, 0x4e0811a1);
+ MD5Transform_II(a, b, c, d, input[4], 6, 0xf7537e82);
+ MD5Transform_II(d, a, b, c, input[11], 10, 0xbd3af235);
+ MD5Transform_II(c, d, a, b, input[2], 15, 0x2ad7d2bb);
+ MD5Transform_II(b, c, d, a, input[9], 21, 0xeb86d391);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/**********************************************************************************
+ *
+ * RC4 Encoding Functions
+ * All Credits go to SirLamer and Raydan
+ * Taken from http://forums.alliedmods.net/showthread.php?t=101834
+ *
+ ***********************************************************************************/
+
+/*
+ * Encrypts a text string using RC4.
+ * Note: This function is NOT binary safe.
+ * Use EncodeRC4Binary to encode binary data.
+ *
+ * @param input The source data to be encrypted.
+ * @param pwd The password/key used to encode and decode the data.
+ * @param output The encoded result.
+ * @param maxlen The maximum length of the output buffer.
+ *
+ * @noreturn
+ */
+stock Crypt_RC4Encode(const String:input[], const String:pwd[], String:output[], maxlen)
+{
+ decl pwd_len,str_len,i,j,a,k;
+ decl key[256];
+ decl box[256];
+ decl tmp;
+
+ pwd_len = strlen(pwd);
+ str_len = strlen(input);
+
+ if (pwd_len > 0 && str_len > 0) {
+
+ for (i=0; i < 256; i++) {
+ key[i] = pwd[i%pwd_len];
+ box[i]=i;
+ }
+
+ i=0; j=0;
+
+ for (; i < 256; i++) {
+ j = (j + box[i] + key[i]) % 256;
+ tmp = box[i];
+ box[i] = box[j];
+ box[j] = tmp;
+ }
+
+ i=0; j=0; a=0;
+
+ for (; i < str_len; i++) {
+ a = (a + 1) % 256;
+ j = (j + box[a]) % 256;
+ tmp = box[a];
+ box[a] = box[j];
+ box[j] = tmp;
+ k = box[((box[a] + box[j]) % 256)];
+ FormatEx(output[2*i], maxlen-2*i, "%02x", input[i] ^ k);
+ }
+ }
+}
+
+/*
+ * Encrypts binary data using RC4.
+ *
+ * @param input The source data to be encrypted.
+ * @param str_len The length of the source data.
+ * @param pwd The password/key used to encode and decode the data.
+ * @param output The encoded result.
+ * @param maxlen The maximum length of the output buffer.
+ * @noreturn
+ */
+stock Crypt_RC4EncodeBinary(const String:input[], str_len, const String:pwd[], String:output[], maxlen)
+{
+ decl pwd_len,i,j,a,k;
+ decl key[256];
+ decl box[256];
+ decl tmp;
+
+ pwd_len = strlen(pwd);
+
+ if (pwd_len > 0 && str_len > 0) {
+
+ for(i=0;i<256;i++) {
+ key[i] = pwd[i%pwd_len];
+ box[i]=i;
+ }
+
+ i=0; j=0;
+
+ for (; i < 256; i++) {
+ j = (j + box[i] + key[i]) % 256;
+ tmp = box[i];
+ box[i] = box[j];
+ box[j] = tmp;
+ }
+
+ i=0; j=0; a=0;
+
+ if (str_len+1 > maxlen) {
+ str_len = maxlen - 1;
+ }
+
+ for(; i < str_len; i++) {
+ a = (a + 1) % 256;
+ j = (j + box[a]) % 256;
+ tmp = box[a];
+ box[a] = box[j];
+ box[j] = tmp;
+ k = box[((box[a] + box[j]) % 256)];
+ FormatEx(output[i], maxlen-i, "%c", input[i] ^ k);
+ }
+
+ /*
+ * i = number of written bits (remember increment occurs at end of for loop, and THEN it fails the loop condition)
+ * Since we're working with binary data, the calling function should not depend on the escape
+ * character, but putting it here prevents crashes in case someone tries to read the data like a string
+ */
+ output[i] = '\0';
+
+ return i;
+ }
+ else {
+ return -1;
+ }
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/debug.inc b/sourcemod-1.5-dev/scripting/include/smlib/debug.inc
new file mode 100644
index 0000000..d0bc141
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/debug.inc
@@ -0,0 +1,30 @@
+#if defined _smlib_debug_included
+ #endinput
+#endif
+#define _smlib_debug_included
+
+#include <sourcemod>
+
+/**
+ * Prints the values of a static Float-Array to the server console.
+ *
+ * @param array Static Float-Array.
+ * @param size Size of the Array.
+ * @noreturn
+ */
+stock Debug_FloatArray(const Float:array[], size=3)
+{
+ new String:output[64] = "";
+
+ for (new i=0; i < size; ++i) {
+
+ if (i > 0 && i < size) {
+ StrCat(output, sizeof(output), ", ");
+
+ }
+
+ Format(output, sizeof(output), "%s%f", output, array[i]);
+ }
+
+ PrintToServer("[DEBUG] Vector[%d] = { %s }", size, output);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/dynarrays.inc b/sourcemod-1.5-dev/scripting/include/smlib/dynarrays.inc
new file mode 100644
index 0000000..8a16011
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/dynarrays.inc
@@ -0,0 +1,24 @@
+#if defined _smlib_dynarray_included
+ #endinput
+#endif
+#define _smlib_dynarray_included
+
+#include <sourcemod>
+
+/**
+ * Retrieves a cell value from an array.
+ * This is a wrapper around the Sourcemod Function GetArrayCell,
+ * but it casts the result as bool
+ *
+ * @param array Array Handle.
+ * @param index Index in the array.
+ * @param block Optionally specify which block to read from
+ * (useful if the blocksize > 0).
+ * @param asChar Optionally read as a byte instead of a cell.
+ * @return Value read.
+ * @error Invalid Handle, invalid index, or invalid block.
+ */
+stock bool:DynArray_GetBool(Handle:array, index, block=0, bool:asChar=false)
+{
+ return bool:GetArrayCell(array, index, block, asChar);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/edicts.inc b/sourcemod-1.5-dev/scripting/include/smlib/edicts.inc
new file mode 100644
index 0000000..7b719aa
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/edicts.inc
@@ -0,0 +1,127 @@
+#if defined _smlib_edicts_included
+ #endinput
+#endif
+#define _smlib_edicts_included
+
+#include <sourcemod>
+#include <smlib/entities>
+
+/*
+ * Finds an edict by it's name
+ * It only finds the first occurence.
+ *
+ * @param name Name of the entity you want so search.
+ * @return Edict Index or INVALID_ENT_REFERENCE if no entity was found.
+ */
+stock Edict_FindByName(const String:name[])
+{
+ new maxEntities = GetMaxEntities();
+ for (new edict=0; edict < maxEntities; edict++) {
+
+ if (!IsValidEdict(edict)) {
+ continue;
+ }
+
+ if (Entity_NameMatches(edict, name)) {
+ return edict;
+ }
+ }
+
+ return INVALID_ENT_REFERENCE;
+}
+
+/*
+ * Finds an edict by its HammerID.
+ * The newer version of Valve's Hammer editor
+ * sets a unique ID for each entity in a map.
+ * It only finds the first occurence.
+ *
+ * @param hammerId Hammer editor ID
+ * @return Edict Index or INVALID_ENT_REFERENCE if no entity was found.
+ */
+stock Edict_FindByHammerId(hammerId)
+{
+ new maxEntities = GetMaxEntities();
+ for (new edict=0; edict < maxEntities; edict++) {
+
+ if (!IsValidEdict(edict)) {
+ continue;
+ }
+
+ if (Entity_GetHammerId(edict) == hammerId) {
+ return edict;
+ }
+ }
+
+ return INVALID_ENT_REFERENCE;
+}
+
+/**
+ * Searches for the closest edict in relation to the given origin
+ *
+ * @param vecOrigin_center 3 dimensional origin array
+ * @param clientsOnly True if you only want to search for clients
+ * @param ignoreEntity Ignore this entity
+ * @return Edict Index or INVALID_ENT_REFERENCE if no entity was found.
+ */
+stock Edict_GetClosest(Float:vecOrigin_center[3], bool:clientsOnly=false, ignoreEntity=-1)
+{
+ decl Float:vecOrigin_edict[3];
+ new Float:smallestDistance = 0.0;
+ new closestEdict = INVALID_ENT_REFERENCE;
+
+ new maxEntities;
+
+ if (clientsOnly) {
+ maxEntities = MaxClients;
+ }
+ else {
+ maxEntities = GetMaxEntities();
+ }
+
+ for (new edict=1; edict <= maxEntities; edict++) {
+
+ if (!IsValidEdict(edict)) {
+ continue;
+ }
+
+ if (ignoreEntity >= 0 && edict == ignoreEntity) {
+ continue;
+ }
+
+ if (GetEntSendPropOffs(edict, "m_vecOrigin") == -1) {
+ continue;
+ }
+
+ Entity_GetAbsOrigin(edict, vecOrigin_edict);
+
+ new Float:edict_distance = GetVectorDistance(vecOrigin_center, vecOrigin_edict, true);
+
+ if (edict_distance < smallestDistance || smallestDistance == 0.0) {
+ smallestDistance = edict_distance;
+ closestEdict = edict;
+ }
+ }
+
+ return closestEdict;
+}
+
+/**
+ * Searches for the closest edict in relation to the given edict.
+ *
+ * @param edict Edict index
+ * @param clientsOnly True if you only want to search for clients
+ * @return The closest edict or INVALID_ENT_REFERENCE
+ */
+stock Edict_GetClosestToEdict(edict, bool:clientsOnly=false)
+{
+ decl Float:vecOrigin[3];
+
+ if (GetEntSendPropOffs(edict, "m_vecOrigin") == -1) {
+ return INVALID_ENT_REFERENCE;
+ }
+
+ Entity_GetAbsOrigin(edict, vecOrigin);
+
+ return Edict_GetClosest(vecOrigin, clientsOnly, edict);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/effects.inc b/sourcemod-1.5-dev/scripting/include/smlib/effects.inc
new file mode 100644
index 0000000..e0b59ca
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/effects.inc
@@ -0,0 +1,743 @@
+#if defined _smlib_effects_included
+ #endinput
+#endif
+#define _smlib_effects_included
+
+#include <sourcemod>
+#include <sdktools_entinput>
+#include <sdktools_tempents>
+#include <sdktools_tempents_stocks>
+#include <smlib/clients>
+#include <smlib/effects>
+#include <smlib/entities>
+#include <smlib/math>
+
+
+
+// Entity Dissolve types
+enum DissolveType
+{
+ DISSOLVE_NORMAL = 0,
+ DISSOLVE_ELECTRICAL,
+ DISSOLVE_ELECTRICAL_LIGHT,
+ DISSOLVE_CORE
+};
+
+/**
+ * Dissolves a player
+ *
+ * @param client Client Index.
+ * @param dissolveType Dissolve Type, use the DissolveType enum.
+ * @param magnitude How strongly to push away from the center.
+ * @return True on success, otherwise false.
+ */
+stock bool:Effect_DissolveEntity(entity, DissolveType:dissolveType=DISSOLVE_NORMAL, magnitude=1)
+{
+ new env_entity_dissolver = CreateEntityByName("env_entity_dissolver");
+
+ if (env_entity_dissolver == -1) {
+ return false;
+ }
+
+ Entity_PointAtTarget(env_entity_dissolver, entity);
+ SetEntProp(env_entity_dissolver, Prop_Send, "m_nDissolveType", _:dissolveType);
+ SetEntProp(env_entity_dissolver, Prop_Send, "m_nMagnitude", magnitude);
+ AcceptEntityInput(env_entity_dissolver, "Dissolve");
+ Entity_Kill(env_entity_dissolver);
+
+ return true;
+}
+
+/**
+ * Dissolves a player's Ragdoll
+ *
+ * @param client Client Index.
+ * @param dissolveType Dissolve Type, use the DissolveType enum.
+ * @return True on success, otherwise false.
+ */
+stock bool:Effect_DissolvePlayerRagDoll(client, DissolveType:dissolveType=DISSOLVE_NORMAL)
+{
+ new m_hRagdoll = GetEntPropEnt(client, Prop_Send, "m_hRagdoll");
+
+ if (m_hRagdoll == -1) {
+ return false;
+ }
+
+ return Effect_DissolveEntity(m_hRagdoll, dissolveType);
+}
+
+functag EffectCallback public(entity, any:data);
+
+/**
+ * Fades an entity in our out.
+ * You can specifiy a callback function which will get called
+ * when the fade is finished.
+ * Important: The callback will be called if it is passed,
+ * no matter if the entity is still valid or not. That means you
+ * have to check if the entity is valid yourself.
+ *
+ * @param entity Entity Index.
+ * @param fadeOut Optional: Fade the entity out (true) or in (false).
+ * @param kill Optional: If to kill the entity when the fade is finished.
+ * @param fast Optional: Fade the entity fast (~0.7 secs) or slow (~3 secs)
+ * @param callback Optional: You can specify a callback Function that will get called when the fade is finished.
+ * @param data Optional: You can pass any data to the callback.
+ * @return True on success, otherwise false.
+ */
+stock Effect_Fade(entity, fadeOut=true, kill=false, fast=true, EffectCallback:callback=INVALID_FUNCTION, any:data=0)
+{
+ new Float:timerTime = 0.0;
+
+ if (fast) {
+ timerTime = 0.6;
+
+ if (fadeOut) {
+ SetEntityRenderFx(entity, RENDERFX_FADE_FAST);
+ }
+ else {
+ SetEntityRenderFx(entity, RENDERFX_SOLID_FAST);
+ }
+ }
+ else {
+ timerTime = 3.0;
+
+ if (fadeOut) {
+ SetEntityRenderFx(entity, RENDERFX_FADE_SLOW);
+ }
+ else {
+ SetEntityRenderFx(entity, RENDERFX_SOLID_SLOW);
+ }
+ }
+
+ ChangeEdictState(entity, GetEntSendPropOffs(entity, "m_nRenderFX", true));
+
+ if (kill || callback != INVALID_FUNCTION) {
+ new Handle:dataPack = INVALID_HANDLE;
+ CreateDataTimer(timerTime, _smlib_Timer_Effect_Fade, dataPack, TIMER_FLAG_NO_MAPCHANGE | TIMER_DATA_HNDL_CLOSE);
+
+ WritePackCell(dataPack, EntIndexToEntRef(entity));
+ WritePackCell(dataPack, kill);
+#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7
+ WritePackFunction(dataPack, callback);
+#else
+ WritePackCell(dataPack, _:callback);
+#endif
+ WritePackCell(dataPack, data);
+ ResetPack(dataPack);
+ }
+}
+
+/**
+ * Fades the entity in.
+ * A wrapper function around Effect_Fade().
+ *
+ * @param entity Entity Index.
+ * @param fast Optional: Fade the entity fast (~0.7 secs) or slow (~3 secs)
+ * @param callback Optional: You can specify a callback Function that will get called when the fade is finished.
+ * @param data Optional: You can pass any data to the callback.
+ * @return True on success, otherwise false.
+ */
+stock Effect_FadeIn(entity, fast=true, EffectCallback:callback=INVALID_FUNCTION, any:data=0)
+{
+ Effect_Fade(entity, false, false, fast, callback, data);
+}
+
+/**
+ * Fades the entity out.
+ * A wrapper function around Effect_Fade().
+ *
+ * @param entity Entity Index.
+ * @param fadeOut Optional: Fade the entity out (true) or in (false).
+ * @param kill Optional: If to kill the entity when the fade is finished.
+ * @param fast Optional: Fade the entity fast (~0.7 secs) or slow (~3 secs)
+ * @param callback Optional: You can specify a callback Function that will get called when the fade is finished.
+ * @param data Optional: You can pass any data to the callback.
+ * @return True on success, otherwise false.
+ */
+stock Effect_FadeOut(entity, kill=false, fast=true, EffectCallback:callback=INVALID_FUNCTION, any:data=0)
+{
+ Effect_Fade(entity, true, kill, fast, callback, data);
+}
+
+public Action:_smlib_Timer_Effect_Fade(Handle:Timer, Handle:dataPack)
+{
+ new entity = ReadPackCell(dataPack);
+ new kill = ReadPackCell(dataPack);
+#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7
+ new Function:callback = ReadPackFunction(dataPack);
+#else
+ new Function:callback = Function:ReadPackCell(dataPack);
+#endif
+ new any:data = any:ReadPackCell(dataPack);
+
+ if (callback != INVALID_FUNCTION) {
+ Call_StartFunction(INVALID_HANDLE, callback);
+ Call_PushCell(entity);
+ Call_PushCell(data);
+ Call_Finish();
+ }
+
+ if (kill && IsValidEntity(entity)) {
+ Entity_Kill(entity);
+ }
+
+ return Plugin_Stop;
+}
+
+/**
+ * Sends a boxed beam effect to one player.
+ *
+ * Ported from eventscripts vecmath library.
+ *
+ * @param client The client to show the box to.
+ * @param bottomCorner One bottom corner of the box.
+ * @param upperCorner One upper corner of the box.
+ * @param modelIndex Precached model index.
+ * @param haloIndex Precached model index.
+ * @param startFrame Initital frame to render.
+ * @param frameRate Beam frame rate.
+ * @param life Time duration of the beam.
+ * @param width Initial beam width.
+ * @param endWidth Final beam width.
+ * @param fadeLength Beam fade time duration.
+ * @param amplitude Beam amplitude.
+ * @param color Color array (r, g, b, a).
+ * @param speed Speed of the beam.
+ * @noreturn
+ */
+stock Effect_DrawBeamBoxToClient(
+ client,
+ const Float:bottomCorner[3],
+ const Float:upperCorner[3],
+ modelIndex,
+ haloIndex,
+ startFrame=0,
+ frameRate=30,
+ Float:life=5.0,
+ Float:width=5.0,
+ Float:endWidth=5.0,
+ fadeLength=2,
+ Float:amplitude=1.0,
+ const color[4]={ 255, 0, 0, 255 },
+ speed=0
+) {
+ new clients[1];
+ clients[0] = client;
+ Effect_DrawBeamBox(clients, 1, bottomCorner, upperCorner, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed);
+}
+
+/**
+ * Sends a boxed beam effect to all players.
+ *
+ * Ported from eventscripts vecmath library.
+ *
+ * @param bottomCorner One bottom corner of the box.
+ * @param upperCorner One upper corner of the box.
+ * @param modelIndex Precached model index.
+ * @param haloIndex Precached model index.
+ * @param startFrame Initital frame to render.
+ * @param frameRate Beam frame rate.
+ * @param life Time duration of the beam.
+ * @param width Initial beam width.
+ * @param endWidth Final beam width.
+ * @param fadeLength Beam fade time duration.
+ * @param amplitude Beam amplitude.
+ * @param color Color array (r, g, b, a).
+ * @param speed Speed of the beam.
+ * @noreturn
+ */
+stock Effect_DrawBeamBoxToAll(
+ const Float:bottomCorner[3],
+ const Float:upperCorner[3],
+ modelIndex,
+ haloIndex,
+ startFrame=0,
+ frameRate=30,
+ Float:life=5.0,
+ Float:width=5.0,
+ Float:endWidth=5.0,
+ fadeLength=2,
+ Float:amplitude=1.0,
+ const color[4]={ 255, 0, 0, 255 },
+ speed=0
+)
+{
+ new clients[MaxClients];
+ new numClients = Client_Get(clients, CLIENTFILTER_INGAME);
+
+ Effect_DrawBeamBox(clients, numClients, bottomCorner, upperCorner, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed);
+}
+
+/**
+ * Sends a boxed beam effect to a list of players.
+ *
+ * Ported from eventscripts vecmath library.
+ *
+ * @param clients An array of clients to show the box to.
+ * @param numClients Number of players in the array.
+ * @param bottomCorner One bottom corner of the box.
+ * @param upperCorner One upper corner of the box.
+ * @param modelIndex Precached model index.
+ * @param haloIndex Precached model index.
+ * @param startFrame Initital frame to render.
+ * @param frameRate Beam frame rate.
+ * @param life Time duration of the beam.
+ * @param width Initial beam width.
+ * @param endWidth Final beam width.
+ * @param fadeLength Beam fade time duration.
+ * @param amplitude Beam amplitude.
+ * @param color Color array (r, g, b, a).
+ * @param speed Speed of the beam.
+ * @noreturn
+ */
+stock Effect_DrawBeamBox(
+ clients[],
+ numClients,
+ const Float:bottomCorner[3],
+ const Float:upperCorner[3],
+ modelIndex,
+ haloIndex,
+ startFrame=0,
+ frameRate=30,
+ Float:life=5.0,
+ Float:width=5.0,
+ Float:endWidth=5.0,
+ fadeLength=2,
+ Float:amplitude=1.0,
+ const color[4]={ 255, 0, 0, 255 },
+ speed=0
+) {
+ // Create the additional corners of the box
+ decl Float:corners[8][3];
+
+ for (new i=0; i < 4; i++) {
+ Array_Copy(bottomCorner, corners[i], 3);
+ Array_Copy(upperCorner, corners[i+4], 3);
+ }
+
+ corners[1][0] = upperCorner[0];
+ corners[2][0] = upperCorner[0];
+ corners[2][1] = upperCorner[1];
+ corners[3][1] = upperCorner[1];
+ corners[4][0] = bottomCorner[0];
+ corners[4][1] = bottomCorner[1];
+ corners[5][1] = bottomCorner[1];
+ corners[7][0] = bottomCorner[0];
+
+ // Draw all the edges
+
+ // Horizontal Lines
+ // Bottom
+ for (new i=0; i < 4; i++) {
+ new j = ( i == 3 ? 0 : i+1 );
+ TE_SetupBeamPoints(corners[i], corners[j], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed);
+ TE_Send(clients, numClients);
+ }
+
+ // Top
+ for (new i=4; i < 8; i++) {
+ new j = ( i == 7 ? 4 : i+1 );
+ TE_SetupBeamPoints(corners[i], corners[j], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed);
+ TE_Send(clients, numClients);
+ }
+
+ // All Vertical Lines
+ for (new i=0; i < 4; i++) {
+ TE_SetupBeamPoints(corners[i], corners[i+4], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed);
+ TE_Send(clients, numClients);
+ }
+}
+
+
+/**
+ * Sends a boxed beam effect to one player.
+ *
+ * Ported from eventscripts vecmath library.
+ *
+ * @param client The client to show the box to.
+ * @param origin Origin/center of the box.
+ * @param mins Min size Vector
+ * @param maxs Max size Vector
+ * @param angles Angles used to rotate the box.
+ * @param modelIndex Precached model index.
+ * @param haloIndex Precached model index.
+ * @param startFrame Initital frame to render.
+ * @param frameRate Beam frame rate.
+ * @param life Time duration of the beam.
+ * @param width Initial beam width.
+ * @param endWidth Final beam width.
+ * @param fadeLength Beam fade time duration.
+ * @param amplitude Beam amplitude.
+ * @param color Color array (r, g, b, a).
+ * @param speed Speed of the beam.
+ * @noreturn
+ */
+stock Effect_DrawBeamBoxRotatableToClient(
+ client,
+ const Float:origin[3],
+ const Float:mins[3],
+ const Float:maxs[3],
+ const Float:angles[3],
+ modelIndex,
+ haloIndex,
+ startFrame=0,
+ frameRate=30,
+ Float:life=5.0,
+ Float:width=5.0,
+ Float:endWidth=5.0,
+ fadeLength=2,
+ Float:amplitude=1.0,
+ const color[4]={ 255, 0, 0, 255 },
+ speed=0
+) {
+ new clients[1];
+ clients[0] = client;
+ Effect_DrawBeamBoxRotatable(clients, 1, origin, mins, maxs, angles, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed);
+}
+
+
+
+/**
+ * Sends a boxed beam effect to all players.
+ *
+ * Ported from eventscripts vecmath library.
+ *
+ * @param origin Origin/center of the box.
+ * @param mins Min size Vector
+ * @param maxs Max size Vector
+ * @param angles Angles used to rotate the box.
+ * @param modelIndex Precached model index.
+ * @param haloIndex Precached model index.
+ * @param startFrame Initital frame to render.
+ * @param frameRate Beam frame rate.
+ * @param life Time duration of the beam.
+ * @param width Initial beam width.
+ * @param endWidth Final beam width.
+ * @param fadeLength Beam fade time duration.
+ * @param amplitude Beam amplitude.
+ * @param color Color array (r, g, b, a).
+ * @param speed Speed of the beam.
+ * @noreturn
+ */
+stock Effect_DrawBeamBoxRotatableToAll(
+ const Float:origin[3],
+ const Float:mins[3],
+ const Float:maxs[3],
+ const Float:angles[3],
+ modelIndex,
+ haloIndex,
+ startFrame=0,
+ frameRate=30,
+ Float:life=5.0,
+ Float:width=5.0,
+ Float:endWidth=5.0,
+ fadeLength=2,
+ Float:amplitude=1.0,
+ const color[4]={ 255, 0, 0, 255 },
+ speed=0
+)
+{
+ new clients[MaxClients];
+ new numClients = Client_Get(clients, CLIENTFILTER_INGAME);
+
+ Effect_DrawBeamBoxRotatable(clients, numClients, origin, mins, maxs, angles, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed);
+}
+
+/**
+ * Sends a boxed beam effect to a list of players.
+ *
+ * Ported from eventscripts vecmath library.
+ *
+ * @param clients An array of clients to show the box to.
+ * @param numClients Number of players in the array.
+ * @param origin Origin/center of the box.
+ * @param mins Min size Vector
+ * @param maxs Max size Vector
+ * @param angles Angles used to rotate the box.
+ * @param modelIndex Precached model index.
+ * @param haloIndex Precached model index.
+ * @param startFrame Initital frame to render.
+ * @param frameRate Beam frame rate.
+ * @param life Time duration of the beam.
+ * @param width Initial beam width.
+ * @param endWidth Final beam width.
+ * @param fadeLength Beam fade time duration.
+ * @param amplitude Beam amplitude.
+ * @param color Color array (r, g, b, a).
+ * @param speed Speed of the beam.
+ * @noreturn
+ */
+stock Effect_DrawBeamBoxRotatable(
+ clients[],
+ numClients,
+ const Float:origin[3],
+ const Float:mins[3],
+ const Float:maxs[3],
+ const Float:angles[3],
+ modelIndex,
+ haloIndex,
+ startFrame=0,
+ frameRate=30,
+ Float:life=5.0,
+ Float:width=5.0,
+ Float:endWidth=5.0,
+ fadeLength=2,
+ Float:amplitude=1.0,
+ const color[4]={ 255, 0, 0, 255 },
+ speed=0
+) {
+ // Create the additional corners of the box
+ decl Float:corners[8][3];
+ Array_Copy(mins, corners[0], 3);
+ Math_MakeVector(maxs[0], mins[1], mins[2], corners[1]);
+ Math_MakeVector(maxs[0], maxs[1], mins[2], corners[2]);
+ Math_MakeVector(mins[0], maxs[1], mins[2], corners[3]);
+ Math_MakeVector(mins[0], mins[1], maxs[2], corners[4]);
+ Math_MakeVector(maxs[0], mins[1], maxs[2], corners[5]);
+ Array_Copy(maxs, corners[6], 3);
+ Math_MakeVector(mins[0], maxs[1], maxs[2], corners[7]);
+
+ // Rotate all edges
+ for (new i=0; i < sizeof(corners); i++) {
+ Math_RotateVector(corners[i], angles, corners[i]);
+ }
+
+ // Apply world offset (after rotation)
+ for (new i=0; i < sizeof(corners); i++) {
+ AddVectors(origin, corners[i], corners[i]);
+ }
+
+ // Draw all the edges
+ // Horizontal Lines
+ // Bottom
+ for (new i=0; i < 4; i++) {
+ new j = ( i == 3 ? 0 : i+1 );
+ TE_SetupBeamPoints(corners[i], corners[j], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed);
+ TE_Send(clients, numClients);
+ }
+
+ // Top
+ for (new i=4; i < 8; i++) {
+ new j = ( i == 7 ? 4 : i+1 );
+ TE_SetupBeamPoints(corners[i], corners[j], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed);
+ TE_Send(clients, numClients);
+ }
+
+ // All Vertical Lines
+ for (new i=0; i < 4; i++) {
+ TE_SetupBeamPoints(corners[i], corners[i+4], modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, color, speed);
+ TE_Send(clients, numClients);
+ }
+}
+
+/**
+ * Displays the given axis of rotation as beam effect to one player.
+ *
+ * @param client The client to show the box to.
+ * @param origin Origin/center of the box.
+ * @param angles Angles used to rotate the box.
+ * @param length The length in each direction.
+ * @param modelIndex Precached model index.
+ * @param haloIndex Precached model index.
+ * @param startFrame Initital frame to render.
+ * @param frameRate Beam frame rate.
+ * @param life Time duration of the beam.
+ * @param width Initial beam width.
+ * @param endWidth Final beam width.
+ * @param fadeLength Beam fade time duration.
+ * @param amplitude Beam amplitude.
+ * @param color Color array (r, g, b, a).
+ * @param speed Speed of the beam.
+ * @noreturn
+ */
+stock Effect_DrawAxisOfRotationToClient(
+ client,
+ const Float:origin[3],
+ const Float:length[3],
+ const Float:angles[3],
+ modelIndex,
+ haloIndex,
+ startFrame=0,
+ frameRate=30,
+ Float:life=5.0,
+ Float:width=5.0,
+ Float:endWidth=5.0,
+ fadeLength=2,
+ Float:amplitude=1.0,
+ speed=0
+) {
+ new clients[1];
+ clients[0] = client;
+ Effect_DrawAxisOfRotation(clients, 1, origin, length, angles, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, speed);
+}
+
+/**
+ * Displays the given axis of rotation as beam effect to all players.
+ *
+ * @param origin Origin/center of the box.
+ * @param angles Angles used to rotate the box.
+ * @param length The length in each direction.
+ * @param modelIndex Precached model index.
+ * @param haloIndex Precached model index.
+ * @param startFrame Initital frame to render.
+ * @param frameRate Beam frame rate.
+ * @param life Time duration of the beam.
+ * @param width Initial beam width.
+ * @param endWidth Final beam width.
+ * @param fadeLength Beam fade time duration.
+ * @param amplitude Beam amplitude.
+ * @param color Color array (r, g, b, a).
+ * @param speed Speed of the beam.
+ * @noreturn
+ */
+stock Effect_DrawAxisOfRotationToAll(
+ const Float:origin[3],
+ const Float:length[3],
+ const Float:angles[3],
+ modelIndex,
+ haloIndex,
+ startFrame=0,
+ frameRate=30,
+ Float:life=5.0,
+ Float:width=5.0,
+ Float:endWidth=5.0,
+ fadeLength=2,
+ Float:amplitude=1.0,
+ speed=0
+)
+{
+ new clients[MaxClients];
+ new numClients = Client_Get(clients, CLIENTFILTER_INGAME);
+
+ Effect_DrawAxisOfRotation(clients, numClients, origin, length, angles, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, speed);
+}
+
+/**
+ * Displays the given axis of rotation as beam effect to a list of players.
+ *
+ * @param clients An array of clients to show the box to.
+ * @param numClients Number of players in the array.
+ * @param origin Origin/center of the box.
+ * @param angles Angles used to rotate the box.
+ * @param length The length in each direction.
+ * @param modelIndex Precached model index.
+ * @param haloIndex Precached model index.
+ * @param startFrame Initital frame to render.
+ * @param frameRate Beam frame rate.
+ * @param life Time duration of the beam.
+ * @param width Initial beam width.
+ * @param endWidth Final beam width.
+ * @param fadeLength Beam fade time duration.
+ * @param amplitude Beam amplitude.
+ * @param color Color array (r, g, b, a).
+ * @param speed Speed of the beam.
+ * @noreturn
+ */
+stock Effect_DrawAxisOfRotation(
+ clients[],
+ numClients,
+ const Float:origin[3],
+ const Float:angles[3],
+ const Float:length[3],
+ modelIndex,
+ haloIndex,
+ startFrame=0,
+ frameRate=30,
+ Float:life=5.0,
+ Float:width=5.0,
+ Float:endWidth=5.0,
+ fadeLength=2,
+ Float:amplitude=1.0,
+ speed=0
+) {
+ // Create the additional corners of the box
+ new Float:xAxis[3], Float:yAxis[3], Float:zAxis[3];
+ xAxis[0] = length[0];
+ yAxis[1] = length[1];
+ zAxis[2] = length[2];
+
+ // Rotate all edges
+ Math_RotateVector(xAxis, angles, xAxis);
+ Math_RotateVector(yAxis, angles, yAxis);
+ Math_RotateVector(zAxis, angles, zAxis);
+
+ // Apply world offset (after rotation)
+ AddVectors(origin, xAxis, xAxis);
+ AddVectors(origin, yAxis, yAxis);
+ AddVectors(origin, zAxis, zAxis);
+
+ // Draw all
+ TE_SetupBeamPoints(origin, xAxis, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, {255, 0, 0, 255}, speed);
+ TE_Send(clients, numClients);
+
+ TE_SetupBeamPoints(origin, yAxis, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, {0, 255, 0, 255}, speed);
+ TE_Send(clients, numClients);
+
+ TE_SetupBeamPoints(origin, zAxis, modelIndex, haloIndex, startFrame, frameRate, life, width, endWidth, fadeLength, amplitude, {0, 0, 255, 255}, speed);
+ TE_Send(clients, numClients);
+}
+
+
+/**
+ * Creates an env_sprite.
+ *
+ * @param origin Origin of the Sprite.
+ * @param modelIndex Precached model index.
+ * @param color Color array (r, g, b, a).
+ * @param scale Scale (Note: many materials ignore a lower value than 0.25).
+ * @param targetName Targetname of the sprite.
+ * @param parent Entity Index of this sprite's parent in the movement hierarchy.
+ * @param renderMode Render mode (use the enum).
+ * @param renderFx Render fx (use the enum).
+ * @param glowProxySize Radius size of the glow when to be rendered, if inside a geometry. Ex: a block 2x2x2 units big, if the glowProxySize is between 0.0 and 2.0 the sprite will not be rendered, even if the actual size of the sprite is bigger, everything above 2.0 will render the sprite. Using an abnormal high value will render Sprites trough walls.
+ * @param frameRate Sprite frame rate.
+ * @param hdrColorScale Float value to multiply sprite color by when running with HDR.
+ * @param receiveShadows When false then this prevents the sprite from receiving shadows.
+ * @return Entity Index of the created Sprite.
+ */
+stock Effect_EnvSprite(
+ const Float:origin[3],
+ modelIndex,
+ const color[4]={255, 255, 255, 255},
+ Float:scale=0.25,
+ const String:targetName[MAX_NAME_LENGTH]="",
+ parent=-1,
+ RenderMode:renderMode=RENDER_WORLDGLOW,
+ RenderFx:renderFx=RENDERFX_NONE,
+ Float:glowProxySize=2.0,
+ Float:framerate=10.0,
+ Float:hdrColorScale=1.0,
+ bool:receiveShadows = true
+) {
+ new entity = Entity_Create("env_sprite");
+
+ if (entity == INVALID_ENT_REFERENCE) {
+ return INVALID_ENT_REFERENCE;
+ }
+
+ DispatchKeyValue (entity, "disablereceiveshadows", (receiveShadows) ? "0" : "1");
+ DispatchKeyValueFloat (entity, "framerate", framerate);
+ DispatchKeyValueFloat (entity, "GlowProxySize", glowProxySize);
+ DispatchKeyValue (entity, "spawnflags", "1");
+ DispatchKeyValueFloat (entity, "HDRColorScale", hdrColorScale);
+ DispatchKeyValue (entity, "maxdxlevel", "0");
+ DispatchKeyValue (entity, "mindxlevel", "0");
+ DispatchKeyValueFloat (entity, "scale", scale);
+
+ DispatchSpawn(entity);
+
+ SetEntityRenderMode(entity, renderMode);
+ SetEntityRenderColor(entity, color[0], color[1], color[2], color[3]);
+ SetEntityRenderFx(entity, renderFx);
+
+ Entity_SetName(entity, targetName);
+ Entity_SetModelIndex(entity, modelIndex);
+ Entity_SetAbsOrigin(entity, origin);
+
+ if (parent != -1) {
+ Entity_SetParent(entity, parent);
+ }
+
+ return entity;
+}
+
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/entities.inc b/sourcemod-1.5-dev/scripting/include/smlib/entities.inc
new file mode 100644
index 0000000..95b5cf2
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/entities.inc
@@ -0,0 +1,2153 @@
+#if defined _smlib_entities_included
+ #endinput
+#endif
+#define _smlib_entities_included
+
+#include <sourcemod>
+#include <sdktools_entinput>
+#include <sdktools_functions>
+
+/**
+ * Macro for iterating trough all children (entities it is parent of) of an entity.
+ *
+ * @param 1 Entity Index of the parent.
+ * @param 2 Name of the children entity index variable (will be only valid in the loop).
+ */
+#define LOOP_CHILDREN(%1,%2) for (new %2=Entity_GetNextChild(%1); %2 != INVALID_ENT_REFERENCE; %2=Entity_GetNextChild(%1, ++%2))
+
+/*
+ * Checks if an entity is valid and exists.
+ *
+ * @param entity Entity Index.
+ * @return True if the entity is valid, false otherwise.
+ */
+stock Entity_IsValid(entity)
+{
+ return IsValidEntity(entity);
+}
+
+/**
+ * Finds an entity by its name.
+ * You can optionally specify the classname to search for.
+ * Note: If the classname is specified it uses The Sourcemod native
+ * function FindEntityByClassname() which uses the engine's
+ * linked entity list for finding entities. This might be
+ * cheaper, use this if you call this function very often.
+ *
+ * @param name Name of the entity you want so search.
+ * @param className Optional: Classname of the entity
+ * @return Entity index or INVALID_ENT_REFERENCE if not matching entity was found.
+ */
+stock Entity_FindByName(const String:name[], const String:className[]="")
+{
+ if (className[0] == '\0') {
+ // Hack: Double the limit to gets none-networked entities too.
+ new realMaxEntities = GetMaxEntities() * 2;
+ for (new entity=0; entity < realMaxEntities; entity++) {
+
+ if (!IsValidEntity(entity)) {
+ continue;
+ }
+
+ if (Entity_NameMatches(entity, name)) {
+ return entity;
+ }
+ }
+ }
+ else {
+ new entity = INVALID_ENT_REFERENCE;
+ while ((entity = FindEntityByClassname(entity, className)) != INVALID_ENT_REFERENCE) {
+
+ if (Entity_NameMatches(entity, name)) {
+ return entity;
+ }
+ }
+ }
+
+ return INVALID_ENT_REFERENCE;
+}
+
+/**
+ * Finds an entity by its HammerID.
+ * The newer version of Valve's Hammer editor
+ * sets a unique ID for each entity in a map.
+ * It only finds the first occurence.
+ * Note: If the classname is specified it uses The Sourcemod native
+ * function FindEntityByClassname() which uses the engine's
+ * linked entity list for finding entities. This might be
+ * cheaper, use this if you call this function very often.
+ *
+ * @param hammerId Hammer editor ID
+ * @param className Optional: Classname of the entity
+ * @return Edict Index or INVALID_ENT_REFERENCE if no entity was found.
+ */
+stock Entity_FindByHammerId(hammerId, const String:className[]="")
+{
+ if (className[0] == '\0') {
+ // Hack: Double the limit to gets none-networked entities too.
+ new realMaxEntities = GetMaxEntities() * 2;
+ for (new entity=0; entity < realMaxEntities; entity++) {
+
+ if (!IsValidEntity(entity)) {
+ continue;
+ }
+
+ if (Entity_GetHammerId(entity) == hammerId) {
+ return entity;
+ }
+ }
+ }
+ else {
+ new entity = INVALID_ENT_REFERENCE;
+ while ((entity = FindEntityByClassname(entity, className)) != INVALID_ENT_REFERENCE) {
+
+ if (Entity_GetHammerId(entity) == hammerId) {
+ return entity;
+ }
+ }
+ }
+
+ return INVALID_ENT_REFERENCE;
+}
+
+/**
+ * Searches for an entity by classname.
+ * This is a wrapper around FindEntityByClassname
+ * and has been added for completion.
+ *
+ * @param startEnt The entity index after which to begin searching from. Use -1 to start from the first entity.
+ * @param classname Classname of the entity to find.
+ * @return Entity index >= 0 if found, -1 otherwise.
+ */
+
+stock Entity_FindByClassName(startEntity, const String:className[])
+{
+ return FindEntityByClassname(startEntity, className);
+}
+
+/**
+ * Checks if an entity (partially) matches a specific entity class.
+ *
+ * @param entity Entity Index.
+ * @param className Classname String.
+ * @partialMatch If to do a partial classname check.
+ * @return True if the classname matches, false otherwise.
+ */
+stock bool:Entity_ClassNameMatches(entity, const String:className[], partialMatch=false)
+{
+ decl String:entity_className[64];
+ Entity_GetClassName(entity, entity_className, sizeof(entity_className));
+
+ if (partialMatch) {
+ return (StrContains(entity_className, className) != -1);
+ }
+
+ return StrEqual(entity_className, className);
+}
+
+/**
+ * Checks if an entity matches a name
+ *
+ * @param entity Entity Index.
+ * @param class Name String.
+ * @return True if the name matches, false otherwise.
+ */
+stock bool:Entity_NameMatches(entity, const String:name[])
+{
+ decl String:entity_name[128];
+ Entity_GetName(entity, entity_name, sizeof(entity_name));
+
+ return StrEqual(name, entity_name);
+}
+
+/**
+ * Gets the Name of an entity.
+ *
+ * @param entity Entity index.
+ * @param buffer Return/Output buffer.
+ * @param size Max size of buffer.
+ * @return Number of non-null bytes written.
+ */
+stock Entity_GetName(entity, String:buffer[], size)
+{
+ return GetEntPropString(entity, Prop_Data, "m_iName", buffer, size);
+}
+
+/**
+ * Sets the Name of an entity.
+ *
+ * @param entity Entity index.
+ * @param name The name you want to give.
+ * @return True on success, false otherwise.
+ */
+stock Entity_SetName(entity, const String:name[], any:...)
+{
+ decl String:format[128];
+ VFormat(format, sizeof(format), name, 3);
+
+ return DispatchKeyValue(entity, "targetname", format);
+}
+
+/**
+ * Gets the Classname of an entity.
+ * This is like GetEdictClassname(), except it works for ALL
+ * entities, not just edicts.
+ *
+ * @param entity Entity index.
+ * @param buffer Return/Output buffer.
+ * @param size Max size of buffer.
+ * @return Number of non-null bytes written.
+ */
+stock Entity_GetClassName(entity, String:buffer[], size)
+{
+ return GetEntPropString(entity, Prop_Data, "m_iClassname", buffer, size);
+}
+
+/**
+ * Sets the Classname of an entity.
+ *
+ * @param entity Entity index.
+ * @param name The name you want to give.
+ * @return True on success, false otherwise.
+ */
+stock Entity_SetClassName(entity, const String:className[])
+{
+ return DispatchKeyValue(entity, "classname", className);
+}
+
+/**
+ * Gets the Target name of an other entity
+ *
+ * @param entity Entity index.
+ * @param buffer Return/Output buffer.
+ * @param size Max size of buffer.
+ * @return Number of non-null bytes written.
+ */
+stock Entity_GetTargetName(entity, String:buffer[], size)
+{
+ return GetEntPropString(entity, Prop_Data, "m_target", buffer, size);
+}
+
+/**
+ * Sets the Target name of an other Entity
+ *
+ * @param entity Entity index.
+ * @param name The target name you want to set
+ * @return True on success, false otherwise.
+ */
+stock Entity_SetTargetName(entity, const String:name[], any:...)
+{
+ decl String:format[128];
+ VFormat(format, sizeof(format), name, 3);
+
+ return DispatchKeyValue(entity, "target", format);
+}
+
+/**
+ * Gets the Global Name of an entity.
+ *
+ * @param entity Entity index.
+ * @param buffer Return/Output buffer.
+ * @param size Max size of buffer.
+ * @return Number of non-null bytes written.
+ */
+stock Entity_GetGlobalName(entity, String:buffer[], size)
+{
+ return GetEntPropString(entity, Prop_Data, "m_iGlobalname", buffer, size);
+}
+
+/**
+ * Sets the Global Name of an entity.
+ *
+ * @param entity Entity index.
+ * @param name The global name you want to set.
+ * @return True on success, false otherwise.
+ */
+stock Entity_SetGlobalName(entity, const String:name[], any:...)
+{
+ decl String:format[128];
+ VFormat(format, sizeof(format), name, 3);
+
+ return DispatchKeyValue(entity, "globalname", format);
+}
+
+/**
+ * Gets the Parent name of an entity.
+ *
+ * @param entity Entity index.
+ * @param buffer Return/Output buffer.
+ * @param size Max size of buffer.
+ * @return Number of non-null bytes written.
+ */
+stock Entity_GetParentName(entity, String:buffer[], size)
+{
+ return GetEntPropString(entity, Prop_Data, "m_iParent", buffer, size);
+}
+
+/**
+ * Sets the Parent name of an entity.
+ *
+ * @param entity Entity index.
+ * @param name The parent name you want to set.
+ * @return True on success, false otherwise.
+ */
+stock Entity_SetParentName(entity, const String:name[], any:...)
+{
+ decl String:format[128];
+ VFormat(format, sizeof(format), name, 3);
+
+ return DispatchKeyValue(entity, "parentname", format);
+}
+
+/**
+ * Gets the Hammer-ID of an entity.
+ * The Hammer Editor gives every entity a unique ID.
+ * Note: Old maps don't have Hammer-ID's set for entities
+ *
+ * @param entity Entity index.
+ * @return Hammer ID.
+ */
+stock Entity_GetHammerId(entity)
+{
+ return GetEntProp(entity, Prop_Data, "m_iHammerID");
+}
+
+/**
+ * Gets the radius (m_flRadius) of an entity.
+ *
+ * @param entity Entity index.
+ * @return Radius
+ */
+stock Float:Entity_GetRadius(entity)
+{
+ return GetEntPropFloat(entity, Prop_Data, "m_flRadius");
+}
+
+/**
+ * Sets the radius (m_flRadius) of an entity.
+ *
+ * @param entity Entity index.
+ * @param radius Radius value
+ * @noreturn
+ */
+stock Entity_SetRadius(entity, Float:radius)
+{
+ SetEntPropFloat(entity, Prop_Data, "m_flRadius", radius);
+}
+
+/**
+ * Gets the Mins of an entity.
+ *
+ * @param entity Entity index.
+ * @param vec Vector.
+ * @noreturn
+ */
+stock Entity_GetMinSize(entity, Float:vec[3])
+{
+ GetEntPropVector(entity, Prop_Send, "m_vecMins", vec);
+}
+
+/**
+ * Sets the Mins of an entity.
+ *
+ * @param entity Entity index.
+ * @param vec Vector.
+ * @noreturn
+ */
+stock Entity_SetMinSize(entity, const Float:vecMins[3])
+{
+ SetEntPropVector(entity, Prop_Send, "m_vecMins", vecMins);
+}
+
+/**
+ * Gets the Mins of an entity.
+ * This functions isn't safe to use, use Entity_SetMinMaxSize() instead.
+ *
+ * @param entity Entity index
+ * @param vec return vector.
+ * @noreturn
+ */
+stock Entity_GetMaxSize(entity, Float:vec[3])
+{
+ GetEntPropVector(entity, Prop_Send, "m_vecMaxs", vec);
+}
+
+/**
+ * Sets the Maxs of an entity.
+ * This functions isn't safe to use, use Entity_SetMinMaxSize() instead.
+ *
+ * @param entity Entity index.
+ * @param vec Vector.
+ * @noreturn
+ */
+stock Entity_SetMaxSize(entity, const Float:vecMaxs[3])
+{
+ SetEntPropVector(entity, Prop_Send, "m_vecMaxs", vecMaxs);
+}
+
+/**
+ * Sets the Min and Max Size of an entity.
+ * Code is taken from HL2SDK and rewritten for Sourcemod.
+ *
+ * @param entity Entity index.
+ * @param vecMins Min size Vector
+ * @param vecMaxs Max size Vector
+ * @noreturn
+ */
+stock Entity_SetMinMaxSize(entity, Float:vecMins[3], Float:vecMaxs[3])
+{
+ // Taken from hl2sdk-ob-valve\game\server\util.cpp SetMinMaxSize()
+ // Todo: Replace this by a SDK call
+ for (new i=0; i<3; i++) {
+
+ if (vecMins[i] > vecMaxs[i]) {
+ ThrowError("Error: mins[%d] > maxs[%d] of entity %d", i, i, EntRefToEntIndex(entity));
+ }
+ }
+
+ decl Float:m_vecMins[3], Float:m_vecMaxs[3];
+ Entity_GetMinSize(entity, m_vecMins);
+ Entity_GetMaxSize(entity, m_vecMaxs);
+
+ if (Math_VectorsEqual(m_vecMins, vecMins) && Math_VectorsEqual(m_vecMaxs, vecMaxs)) {
+ return;
+ }
+
+ Entity_SetMinSize(entity, vecMins);
+ Entity_SetMaxSize(entity, vecMaxs);
+
+ decl Float:vecSize[3];
+ SubtractVectors(vecMaxs, vecMins, vecSize);
+ Entity_SetRadius(entity, GetVectorLength(vecSize) * 0.5);
+
+ Entity_MarkSurrBoundsDirty(entity);
+}
+
+/*
+ * Spawn Flags
+ * Many entities define their specific spawnflags, check the HL2SDK.
+ */
+
+/*
+ * Phys prop spawnflags
+ * Taken from hl2sdk-ob-valve\game\shared\props_shared.h
+ */
+#define SF_PHYSPROP_START_ASLEEP 0x000001
+#define SF_PHYSPROP_DONT_TAKE_PHYSICS_DAMAGE 0x000002 // this prop can't be damaged by physics collisions
+#define SF_PHYSPROP_DEBRIS 0x000004
+#define SF_PHYSPROP_MOTIONDISABLED 0x000008 // motion disabled at startup (flag only valid in spawn - motion can be enabled via input)
+#define SF_PHYSPROP_TOUCH 0x000010 // can be 'crashed through' by running player (plate glass)
+#define SF_PHYSPROP_PRESSURE 0x000020 // can be broken by a player standing on it
+#define SF_PHYSPROP_ENABLE_ON_PHYSCANNON 0x000040 // enable motion only if the player grabs it with the physcannon
+#define SF_PHYSPROP_NO_ROTORWASH_PUSH 0x000080 // The rotorwash doesn't push these
+#define SF_PHYSPROP_ENABLE_PICKUP_OUTPUT 0x000100 // If set, allow the player to +USE this for the purposes of generating an output
+#define SF_PHYSPROP_PREVENT_PICKUP 0x000200 // If set, prevent +USE/Physcannon pickup of this prop
+#define SF_PHYSPROP_PREVENT_PLAYER_TOUCH_ENABLE 0x000400 // If set, the player will not cause the object to enable its motion when bumped into
+#define SF_PHYSPROP_HAS_ATTACHED_RAGDOLLS 0x000800 // Need to remove attached ragdolls on enable motion/etc
+#define SF_PHYSPROP_FORCE_TOUCH_TRIGGERS 0x001000 // Override normal debris behavior and respond to triggers anyway
+#define SF_PHYSPROP_FORCE_SERVER_SIDE 0x002000 // Force multiplayer physics object to be serverside
+#define SF_PHYSPROP_RADIUS_PICKUP 0x004000 // For Xbox, makes small objects easier to pick up by allowing them to be found
+#define SF_PHYSPROP_ALWAYS_PICK_UP 0x100000 // Physcannon can always pick this up, no matter what mass or constraints may apply.
+#define SF_PHYSPROP_NO_COLLISIONS 0x200000 // Don't enable collisions on spawn
+#define SF_PHYSPROP_IS_GIB 0x400000 // Limit # of active gibs
+
+/*
+ * Physbox Spawnflags. Start at 0x01000 to avoid collision with CBreakable's
+ * Taken from hl2sdk-ob-valve\game\server\physobj.h
+ */
+#define SF_PHYSBOX_ASLEEP 0x01000
+#define SF_PHYSBOX_IGNOREUSE 0x02000
+#define SF_PHYSBOX_DEBRIS 0x04000
+#define SF_PHYSBOX_MOTIONDISABLED 0x08000
+#define SF_PHYSBOX_USEPREFERRED 0x10000
+#define SF_PHYSBOX_ENABLE_ON_PHYSCANNON 0x20000
+#define SF_PHYSBOX_NO_ROTORWASH_PUSH 0x40000 // The rotorwash doesn't push these
+#define SF_PHYSBOX_ENABLE_PICKUP_OUTPUT 0x80000
+#define SF_PHYSBOX_ALWAYS_PICK_UP 0x100000 // Physcannon can always pick this up, no matter what mass or constraints may apply.
+#define SF_PHYSBOX_NEVER_PICK_UP 0x200000 // Physcannon will never be able to pick this up.
+#define SF_PHYSBOX_NEVER_PUNT 0x400000 // Physcannon will never be able to punt this object.
+#define SF_PHYSBOX_PREVENT_PLAYER_TOUCH_ENABLE 0x800000 // If set, the player will not cause the object to enable its motion when bumped into
+
+/*
+ * Spawnflags for func breakable
+ * Taken from hl2sdk-ob-valve\game\server\func_break.h
+ */
+#define SF_BREAK_TRIGGER_ONLY 0x0001 // may only be broken by trigger
+#define SF_BREAK_TOUCH 0x0002 // can be 'crashed through' by running player (plate glass)
+#define SF_BREAK_PRESSURE 0x0004 // can be broken by a player standing on it
+#define SF_BREAK_PHYSICS_BREAK_IMMEDIATELY 0x0200 // the first physics collision this breakable has will immediately break it
+#define SF_BREAK_DONT_TAKE_PHYSICS_DAMAGE 0x0400 // this breakable doesn't take damage from physics collisions
+#define SF_BREAK_NO_BULLET_PENETRATION 0x0800 // don't allow bullets to penetrate
+
+/*
+ * Spawnflags for func_pushable (it's also func_breakable, so don't collide with those flags)
+ * Taken from hl2sdk-ob-valve\game\server\func_break.h
+ */
+#define SF_PUSH_BREAKABLE 0x0080
+#define SF_PUSH_NO_USE 0x0100 // player cannot +use pickup this ent
+
+/**
+ * Gets the Spawnflags of an entity.
+ *
+ * @param entity Entity index.
+ * @return Spawnflags value
+ */
+stock Entity_GetSpawnFlags(entity)
+{
+ return GetEntProp(entity, Prop_Data, "m_spawnflags");
+}
+
+/**
+ * Sets the Spawnflags of an entity.
+ *
+ * @param entity Entity index.
+ * @param flags Flags value
+ * @noreturn
+ */
+stock Entity_SetSpawnFlags(entity, flags)
+{
+ SetEntProp(entity, Prop_Data, "m_spawnflags", flags);
+}
+
+/**
+ * Adds Spawnflags to an entity.
+ *
+ * @param entity Entity index.
+ * @param flags Flags value
+ * @noreturn
+ */
+stock Entity_AddSpawnFlags(entity, flags)
+{
+ new spawnFlags = Entity_GetSpawnFlags(entity);
+ spawnFlags |= flags;
+ Entity_SetSpawnFlags(entity, spawnFlags);
+}
+
+/**
+ * Removes Spawnflags from an entity.
+ *
+ * @param entity Entity index.
+ * @param flags Flags value
+ * @noreturn
+ */
+stock Entity_RemoveSpawnFlags(entity, flags)
+{
+ new spawnFlags = Entity_GetSpawnFlags(entity);
+ spawnFlags &= ~flags;
+ Entity_SetSpawnFlags(entity, spawnFlags);
+}
+
+/**
+ * Clears all Spawnflags of an entity.
+ *
+ * @param entity Entity index.
+ * @noreturn
+ */
+stock Entity_ClearSpawnFlags(entity)
+{
+ Entity_SetSpawnFlags(entity, 0);
+}
+
+/**
+ * Returns whether the entity has specific Spawnflags.
+ *
+ * @param entity Entity index.
+ * @param flags Flags value.
+ * @return True if the entity has the spawnflags set, false otherwise.
+ */
+stock bool:Entity_HasSpawnFlags(entity, flags)
+{
+ return bool:(Entity_GetSpawnFlags(entity) & flags);
+}
+
+/*
+ * Entity flags, CBaseEntity::m_iEFlags
+ * Taken from: hl2sdk-ob-valve\game\shared\shareddefs.h
+ */
+enum Entity_Flags
+{
+ EFL_KILLME = (1<<0), // This entity is marked for death -- This allows the game to actually delete ents at a safe time
+ EFL_DORMANT = (1<<1), // Entity is dormant, no updates to client
+ EFL_NOCLIP_ACTIVE = (1<<2), // Lets us know when the noclip command is active.
+ EFL_SETTING_UP_BONES = (1<<3), // Set while a model is setting up its bones.
+ EFL_KEEP_ON_RECREATE_ENTITIES = (1<<4), // This is a special entity that should not be deleted when we restart entities only
+
+ EFL_HAS_PLAYER_CHILD= (1<<4), // One of the child entities is a player.
+
+ EFL_DIRTY_SHADOWUPDATE = (1<<5), // Client only- need shadow manager to update the shadow...
+ EFL_NOTIFY = (1<<6), // Another entity is watching events on this entity (used by teleport)
+
+ // The default behavior in ShouldTransmit is to not send an entity if it doesn't
+ // have a model. Certain entities want to be sent anyway because all the drawing logic
+ // is in the client DLL. They can set this flag and the engine will transmit them even
+ // if they don't have a model.
+ EFL_FORCE_CHECK_TRANSMIT = (1<<7),
+
+ EFL_BOT_FROZEN = (1<<8), // This is set on bots that are frozen.
+ EFL_SERVER_ONLY = (1<<9), // Non-networked entity.
+ EFL_NO_AUTO_EDICT_ATTACH = (1<<10), // Don't attach the edict; we're doing it explicitly
+
+ // Some dirty bits with respect to abs computations
+ EFL_DIRTY_ABSTRANSFORM = (1<<11),
+ EFL_DIRTY_ABSVELOCITY = (1<<12),
+ EFL_DIRTY_ABSANGVELOCITY = (1<<13),
+ EFL_DIRTY_SURR_COLLISION_BOUNDS = (1<<14),
+ EFL_DIRTY_SPATIAL_PARTITION = (1<<15),
+// UNUSED = (1<<16),
+
+ EFL_IN_SKYBOX = (1<<17), // This is set if the entity detects that it's in the skybox.
+ // This forces it to pass the "in PVS" for transmission.
+ EFL_USE_PARTITION_WHEN_NOT_SOL = (1<<18), // Entities with this flag set show up in the partition even when not solid
+ EFL_TOUCHING_FLUID = (1<<19), // Used to determine if an entity is floating
+
+ // FIXME: Not really sure where I should add this...
+ EFL_IS_BEING_LIFTED_BY_BARNACLE = (1<<20),
+ EFL_NO_ROTORWASH_PUSH = (1<<21), // I shouldn't be pushed by the rotorwash
+ EFL_NO_THINK_FUNCTION = (1<<22),
+ EFL_NO_GAME_PHYSICS_SIMULATION = (1<<23),
+
+ EFL_CHECK_UNTOUCH = (1<<24),
+ EFL_DONTBLOCKLOS = (1<<25), // I shouldn't block NPC line-of-sight
+ EFL_DONTWALKON = (1<<26), // NPC;s should not walk on this entity
+ EFL_NO_DISSOLVE = (1<<27), // These guys shouldn't dissolve
+ EFL_NO_MEGAPHYSCANNON_RAGDOLL = (1<<28), // Mega physcannon can't ragdoll these guys.
+ EFL_NO_WATER_VELOCITY_CHANGE = (1<<29), // Don't adjust this entity's velocity when transitioning into water
+ EFL_NO_PHYSCANNON_INTERACTION = (1<<30), // Physcannon can't pick these up or punt them
+ EFL_NO_DAMAGE_FORCES = (1<<31), // Doesn't accept forces from physics damage
+};
+
+/**
+ * Gets the Entity flags (m_iEFlags) of an entity.
+ *
+ * @param entity Entity index.
+ * @return Entity flags value
+ */
+stock Entity_Flags:Entity_GetEFlags(entity)
+{
+ return Entity_Flags:GetEntProp(entity, Prop_Data, "m_iEFlags");
+}
+
+/**
+ * Sets the entity's Entity flags (m_iEFlags).
+ *
+ * @param entity Entity index.
+ * @param flags Flags value
+ * @noreturn
+ */
+stock Entity_SetEFlags(entity, Entity_Flags:flags)
+{
+ SetEntProp(entity, Prop_Data, "m_iEFlags", flags);
+}
+
+/**
+ * Adds Entity flags (m_iEFlags) to an entity.
+ *
+ * @param entity Entity index.
+ * @param flags Flags value
+ * @noreturn
+ */
+stock Entity_AddEFlags(entity, Entity_Flags:flags)
+{
+ new Entity_Flags:setFlags = Entity_GetEFlags(entity);
+ setFlags |= flags;
+ Entity_SetEFlags(entity, setFlags);
+}
+
+/**
+ * Removes Entity flags (m_iEFlags) from an entity.
+ *
+ * @param entity Entity index.
+ * @param flags Flags value
+ * @noreturn
+ */
+stock Entity_RemoveEFlags(entity, Entity_Flags:flags)
+{
+ new Entity_Flags:setFlags = Entity_GetEFlags(entity);
+ setFlags &= ~flags;
+ Entity_SetEFlags(entity, setFlags);
+}
+
+/**
+ * Checks if the entity has specific Entity flags (m_iEFlags) set.
+ *
+ * @param entity Entity index.
+ * @param flags Flags value
+ * @return True if the flags are set, false otherwise.
+ */
+stock bool:Entity_HasEFlags(entity, Entity_Flags:flags)
+{
+ new Entity_Flags:currentEFlags = Entity_GetEFlags(entity);
+
+ return bool:(currentEFlags & flags);
+}
+
+/**
+ * Marks the surrounding bounds of an entity as outdated.
+ * You normally call this when a collision setting has changed.
+ *
+ * @param entity Entity index.
+ * @noreturn
+ */
+stock Entity_MarkSurrBoundsDirty(entity)
+{
+ Entity_AddEFlags(entity, EFL_DIRTY_SURR_COLLISION_BOUNDS);
+}
+
+/*
+ * CBaseEntity::m_fFlags Functions
+ * Use the FL_ Defines (FL_ONGROUND, ...) or
+ * special entity specific flags.
+ * Note: The flag FL_AIMTARGET probably doesn't work as
+ * we have current no way of adding/removing it to the AimTarget List.
+ */
+
+/**
+ * Gets the Flags of an entity.
+ *
+ * @param entity Entity Index.
+ * @return Entity Flags.
+ */
+stock Entity_GetFlags(entity)
+{
+ return GetEntProp(entity, Prop_Data, "m_fFlags");
+}
+
+/**
+ * Sets the Flags of an entity.
+ *
+ * @param entity Entity index.
+ * @param flags New Flags value
+ * @noreturn
+ */
+stock Entity_SetFlags(entity, flags)
+{
+ SetEntProp(entity, Prop_Data, "m_fFlags", flags);
+}
+
+/**
+ * Adds Flags to the entity
+ *
+ * @param entity Entity index.
+ * @param flags Flags to add
+ * @noreturn
+ */
+stock Entity_AddFlags(entity, flags)
+{
+ new setFlags = Entity_GetFlags(entity);
+ setFlags |= flags;
+ Entity_SetFlags(entity, flags);
+}
+
+/**
+ * Removes flags from the entity
+ *
+ * @param entity Entity index.
+ * @param flags Flags to remove
+ * @noreturn
+ */
+stock Entity_RemoveFlags(entity, flags)
+{
+ new setFlags = Entity_GetFlags(entity);
+ setFlags &= ~flags;
+ Entity_SetFlags(entity, setFlags);
+}
+
+/**
+ * Toggles the specified flag on the entity.
+ * Adds the flag to the entity if it doesn't exists
+ * or removes it otherwise.
+ *
+ * @param entity Entity index.
+ * @param flags Flag to Toggle
+ * @noreturn
+ */
+stock Entity_ToggleFlag(entity, flag)
+{
+ new setFlag = Entity_GetFlags(entity);
+ setFlag ^= flag;
+ Entity_SetFlags(entity, setFlag);
+}
+
+/**
+ * Removes all flags from the entity
+ *
+ * @param entity Entity index.
+ * @noreturn
+ */
+stock Entity_ClearFlags(entity)
+{
+ Entity_SetFlags(entity, 0);
+}
+
+/* edict->solid values
+ * NOTE: Some movetypes will cause collisions independent of SOLID_NOT/SOLID_TRIGGER when the entity moves
+ * SOLID only effects OTHER entities colliding with this one when they move - UGH!
+ *
+ * Solid type basically describes how the bounding volume of the object is represented
+ * NOTE: These numerical values are used in the FGD by the prop code (see prop_dynamic)
+ * Taken from: hl2sdk-ob-valve\public\const.h
+ */
+
+enum SolidFlags_t
+{
+ FSOLID_CUSTOMRAYTEST = 0x0001, // Ignore solid type + always call into the entity for ray tests
+ FSOLID_CUSTOMBOXTEST = 0x0002, // Ignore solid type + always call into the entity for swept box tests
+ FSOLID_NOT_SOLID = 0x0004, // Are we currently not solid?
+ FSOLID_TRIGGER = 0x0008, // This is something may be collideable but fires touch functions
+ // even when it's not collideable (when the FSOLID_NOT_SOLID flag is set)
+ FSOLID_NOT_STANDABLE = 0x0010, // You can't stand on this
+ FSOLID_VOLUME_CONTENTS = 0x0020, // Contains volumetric contents (like water)
+ FSOLID_FORCE_WORLD_ALIGNED = 0x0040, // Forces the collision rep to be world-aligned even if it's SOLID_BSP or SOLID_VPHYSICS
+ FSOLID_USE_TRIGGER_BOUNDS = 0x0080, // Uses a special trigger bounds separate from the normal OBB
+ FSOLID_ROOT_PARENT_ALIGNED = 0x0100, // Collisions are defined in root parent's local coordinate space
+ FSOLID_TRIGGER_TOUCH_DEBRIS = 0x0200, // This trigger will touch debris objects
+
+ FSOLID_MAX_BITS = 10
+};
+
+/**
+ * Gets the solid flags of the entity
+ *
+ * @param entity Entity index.
+ * @return Solid Flags.
+ */
+stock SolidFlags_t:Entity_GetSolidFlags(entity)
+{
+ return SolidFlags_t:GetEntProp(entity, Prop_Data, "m_usSolidFlags", 2);
+}
+
+/**
+ * Sets the solid flags of the entity
+ *
+ * @param entity Entity index.
+ * @param flags Solid Flags.
+ * @noreturn
+ */
+stock Entity_SetSolidFlags(entity, SolidFlags_t:flags)
+{
+ new SolidFlags_t:oldFlags = Entity_GetSolidFlags(entity);
+ flags = flags & SolidFlags_t:0xFFFF;
+
+ if (oldFlags == flags) {
+ return;
+ }
+
+ SetEntProp(entity, Prop_Data, "m_usSolidFlags", flags, 2);
+
+ // These two flags, if changed, can produce different surrounding bounds
+ if ((oldFlags & (FSOLID_FORCE_WORLD_ALIGNED | FSOLID_USE_TRIGGER_BOUNDS)) !=
+ (flags & (FSOLID_FORCE_WORLD_ALIGNED | FSOLID_USE_TRIGGER_BOUNDS)))
+ {
+ Entity_MarkSurrBoundsDirty(entity);
+ }
+}
+
+/**
+ * Adds solid flags to the entity
+ *
+ * @param entity Entity index.
+ * @param flags Solid Flags.
+ * @noreturn
+ */
+stock Entity_AddSolidFlags(entity, SolidFlags_t:flags)
+{
+ new SolidFlags_t:newFlags = Entity_GetSolidFlags(entity);
+ newFlags |= flags;
+ Entity_SetSolidFlags(entity, newFlags);
+}
+
+/**
+ * Removes solid flags from the entity.
+ *
+ * @param entity Entity index.
+ * @param flags Solid Flags.
+ * @noreturn
+ */
+stock Entity_RemoveSolidFlags(entity, SolidFlags_t:flags)
+{
+ new SolidFlags_t:newFlags = Entity_GetSolidFlags(entity);
+ newFlags &= ~flags;
+ Entity_SetSolidFlags(entity, newFlags);
+}
+
+/**
+ * Removes all solid flags from the entity.
+ *
+ * @param entity Entity index.
+ * @noreturn
+ */
+stock Entity_ClearSolidFlags(entity)
+{
+ Entity_SetSolidFlags(entity, SolidFlags_t:0);
+}
+
+/**
+ * Checks whether certain solid flags are set on the entity.
+ *
+ * @param entity Entity index.
+ * @param flags Solid Flags.
+ * @return True if the specified flags are set, false otherwise.
+ */
+stock bool:Entity_SolidFlagsSet(entity, SolidFlags_t:flagMask)
+{
+ return bool:(Entity_GetSolidFlags(entity) & flagMask);
+}
+
+enum SolidType_t
+{
+ SOLID_NONE = 0, // no solid model
+ SOLID_BSP = 1, // a BSP tree
+ SOLID_BBOX = 2, // an AABB
+ SOLID_OBB = 3, // an OBB (not implemented yet)
+ SOLID_OBB_YAW = 4, // an OBB, constrained so that it can only yaw
+ SOLID_CUSTOM = 5, // Always call into the entity for tests
+ SOLID_VPHYSICS = 6, // solid vphysics object, get vcollide from the model and collide with that
+ SOLID_LAST,
+};
+
+/**
+ * Gets the solidity type of the entity
+ *
+ * @param entity Entity index.
+ * @return Solid Type
+ */
+stock SolidType_t:Entity_GetSolidType(entity)
+{
+ return SolidType_t:GetEntProp(entity, Prop_Data, "m_nSolidType", 1);
+}
+
+/**
+ * Sets the solidity type of the entity
+ *
+ * @param entity Entity index.
+ * @param Solid Type value.
+ * @noreturn
+ */
+stock Entity_SetSolidType(entity, SolidType_t:value)
+{
+ SetEntProp(entity, Prop_Send, "m_nSolidType", value, 1);
+ Entity_MarkSurrBoundsDirty(entity);
+}
+
+/**
+ * Checks whether the entity is solid or not.
+ *
+ * @param entity Entity index.
+ * @return True if the entity is solid, false otherwise.
+ */
+stock bool:Entity_IsSolid(entity)
+{
+ return (Entity_GetSolidType(entity) != SOLID_NONE &&
+ !Entity_SolidFlagsSet(entity, FSOLID_NOT_SOLID));
+}
+
+/**
+ * Retrieves the model path of a given entity.
+ * Returns "*num" for Brush entities.
+ *
+ * @param entity entity reference or index
+ * @param model buffer String for the model
+ * @param size max size of buffer string
+ * @return Number of non-null bytes written.
+ */
+stock Entity_GetModel(entity, String:buffer[], size)
+{
+ return GetEntPropString(entity, Prop_Data, "m_ModelName", buffer, size);
+}
+
+/**
+ * Sets the model to a given entity.
+ * Be sure it has been precached.
+ * This is an alias for SetEntityModel()
+ *
+ * @param entity Entity index
+ * @param model Model name
+ * @noreturn
+ */
+stock Entity_SetModel(entity, const String:model[])
+{
+ SetEntityModel(entity, model);
+}
+
+/**
+ * Gets the entity's model index, if it has one set.
+ *
+ * @param entity Entity index.
+ * @return The Entity's model index
+ */
+stock Entity_GetModelIndex(entity)
+{
+ return GetEntProp(entity, Prop_Data, "m_nModelIndex", 2);
+}
+
+/**
+ * Sets the entity's model index (must be precached)
+ *
+ * @param entity Entity index.
+ * @param index Model Index.
+ * @noreturn
+ */
+stock Entity_SetModelIndex(entity, index)
+{
+ SetEntProp(entity, Prop_Data, "m_nModelIndex", index, 2);
+}
+
+/**
+* Sets the entity's maxspeed to the given value (in units per second)
+*
+* @param entity Entity index
+* @param maxspeed the maximum speed the entity can move
+* @noreturn
+*/
+stock Entity_SetMaxSpeed(entity, Float:value)
+{
+ SetEntPropFloat(entity, Prop_Data, "m_flMaxspeed", value);
+}
+
+/*
+ * Collision groups
+ * Taken from hl2sdk-ob-valve/public/const.h
+ */
+enum Collision_Group_t
+{
+ COLLISION_GROUP_NONE = 0,
+ COLLISION_GROUP_DEBRIS, // Collides with nothing but world and static stuff
+ COLLISION_GROUP_DEBRIS_TRIGGER, // Same as debris, but hits triggers
+ COLLISION_GROUP_INTERACTIVE_DEB, // Collides with everything except other interactive debris or debris
+ COLLISION_GROUP_INTERACTIVE, // Collides with everything except interactive debris or debris
+ COLLISION_GROUP_PLAYER,
+ COLLISION_GROUP_BREAKABLE_GLASS,
+ COLLISION_GROUP_VEHICLE,
+ COLLISION_GROUP_PLAYER_MOVEMENT, // For HL2, same as Collision_Group_Player, for
+ // TF2, this filters out other players and CBaseObjects
+ COLLISION_GROUP_NPC, // Generic NPC group
+ COLLISION_GROUP_IN_VEHICLE, // for any entity inside a vehicle
+ COLLISION_GROUP_WEAPON, // for any weapons that need collision detection
+ COLLISION_GROUP_VEHICLE_CLIP, // vehicle clip brush to restrict vehicle movement
+ COLLISION_GROUP_PROJECTILE, // Projectiles!
+ COLLISION_GROUP_DOOR_BLOCKER, // Blocks entities not permitted to get near moving doors
+ COLLISION_GROUP_PASSABLE_DOOR, // Doors that the player shouldn't collide with
+ COLLISION_GROUP_DISSOLVING, // Things that are dissolving are in this group
+ COLLISION_GROUP_PUSHAWAY, // Nonsolid on client and server, pushaway in player code
+
+ COLLISION_GROUP_NPC_ACTOR, // Used so NPCs in scripts ignore the player.
+ COLLISION_GROUP_NPC_SCRIPTED // USed for NPCs in scripts that should not collide with each other
+};
+
+/**
+ * Gets the collision group of an entity.
+ *
+ * @param entity entity index
+ * @return Entity collision group.
+ */
+stock Collision_Group_t:Entity_GetCollisionGroup(entity)
+{
+ return Collision_Group_t:GetEntProp(entity, Prop_Data, "m_CollisionGroup");
+}
+
+/**
+ * Sets the collision group of an entity.
+ *
+ * @param entity entity index
+ * @param value the new collision group.
+ * @noreturn
+ */
+stock Entity_SetCollisionGroup(entity, Collision_Group_t:value)
+{
+ SetEntProp(entity, Prop_Data, "m_CollisionGroup", value);
+}
+
+/**
+ * Functions for getting / setting the origin (position) of an entity.
+ * Go to http://developer.valvesoftware.com/wiki/Origin
+ * if you want to learn more about origins
+ */
+
+/**
+ * Gets the Absolute Origin (position) of an entity.
+ *
+ * @param entity Entity index.
+ * @param vec 3 dimensional vector array.
+ * @noreturn
+ */
+stock Entity_GetAbsOrigin(entity, Float:vec[3])
+{
+ GetEntPropVector(entity, Prop_Send, "m_vecOrigin", vec);
+}
+
+/**
+ * Sets the Absolute Origin (position) of an entity.
+ *
+ * @param entity Entity index.
+ * @param vec 3 dimensional vector array.
+ * @noreturn
+ */
+stock Entity_SetAbsOrigin(entity, const Float:vec[3])
+{
+ // We use TeleportEntity to set the origin more safely
+ // Todo: Replace this with a call to UTIL_SetOrigin() or CBaseEntity::SetLocalOrigin()
+ TeleportEntity(entity, vec, NULL_VECTOR, NULL_VECTOR);
+}
+
+/**
+ * Functions for getting / setting the angles (rotation) of an entity.
+ * http://developer.valvesoftware.com/wiki/Angles
+ * if you want to learn more about angles
+ */
+
+/**
+ * Gets the Angles of an entity
+ *
+ * @param entity Entity index.
+ * @param vec 3 dimensional vector array.
+ * @noreturn
+ */
+stock Entity_GetAbsAngles(entity, Float:vec[3])
+{
+ GetEntPropVector(entity, Prop_Data, "m_angAbsRotation", vec);
+}
+
+/**
+ * Sets the Angles of an entity
+ *
+ * @param entity Entity index.
+ * @param vec 3 dimensional vector array.
+ * @noreturn
+ */
+stock Entity_SetAbsAngles(entity, const Float:vec[3])
+{
+ // We use TeleportEntity to set the angles more safely
+ // Todo: Replace this with a call to CBaseEntity::SetLocalAngles()
+ TeleportEntity(entity, NULL_VECTOR, vec, NULL_VECTOR);
+}
+
+/**
+ * Functions for getting / setting the velocity of an entity.
+ * Go to http://developer.valvesoftware.com/wiki/Velocity
+ * if you want to learn more about the different kind of velocities.
+ */
+
+/**
+ * Gets the Local velocity of an entity.
+ * The local velocity is the velocity generated by the entity.
+ *
+ * @param entity Entity index.
+ * @param vel An 3 dim array
+ * @noreturn
+ */
+stock Entity_GetLocalVelocity(entity, Float:vec[3])
+{
+ GetEntPropVector(entity, Prop_Data, "m_vecVelocity", vec);
+}
+
+/**
+ * Sets the Local velocity of an entity.
+ * The local velocity is the velocity generated by the entity.
+ * Only use this if you know what you are doing,
+ * the entity can overwrite this value on next frame.
+ *
+ * @param entity Entity index.
+ * @param vel An 3 dim array
+ * @noreturn
+ */
+stock Entity_SetLocalVelocity(entity, const Float:vec[3])
+{
+ SetEntPropVector(entity, Prop_Data, "m_vecVelocity", vec);
+}
+
+/**
+ * Gets the Base velocity of an entity.
+ * The base velocity is the velocity applied
+ * to the entity from other sources .
+ *
+ * @param entity Entity index.
+ * @param vel An 3 dim array
+ * @noreturn
+ */
+stock Entity_GetBaseVelocity(entity, Float:vec[3])
+{
+ GetEntPropVector(entity, Prop_Data, "m_vecBaseVelocity", vec);
+}
+
+/**
+ * Sets the Base velocity of an entity.
+ * The base velocity is the velocity applied
+ * to the entity from other sources .
+ *
+ * @param entity Entity index.
+ * @param vel An 3 dim array
+ * @noreturn
+ */
+stock Entity_SetBaseVelocity(entity, const Float:vec[3])
+{
+ SetEntPropVector(entity, Prop_Data, "m_vecBaseVelocity", vec);
+}
+
+/**
+ * Gets the Absolute velocity of an entity.
+ * The absolute velocity is the sum of the local
+ * and base velocities. It's the actual value used to move.
+ *
+ * @param entity Entity index.
+ * @param vel An 3 dim array
+ * @noreturn
+ */
+stock Entity_GetAbsVelocity(entity, Float:vec[3])
+{
+ GetEntPropVector(entity, Prop_Data, "m_vecAbsVelocity", vec);
+}
+
+/**
+ * Sets the Absolute velocity of an entity.
+ * The absolute velocity is the sum of the local
+ * and base velocities. It's the actual value used to move.
+ *
+ * @param entity Entity index.
+ * @param vel An 3 dim array
+ * @noreturn
+ */
+stock Entity_SetAbsVelocity(entity, const Float:vec[3])
+{
+ // We use TeleportEntity to set the velocity more safely
+ // Todo: Replace this with a call to CBaseEntity::SetAbsVelocity()
+ TeleportEntity(entity, NULL_VECTOR, NULL_VECTOR, vec);
+}
+
+/**
+ * Returns true if the entity is locked.
+ *
+ * @param entity Entity index.
+ * @return True if locked otherwise false.
+ */
+stock bool:Entity_IsLocked(entity)
+{
+ return bool:GetEntProp(entity, Prop_Data, "m_bLocked", 1);
+}
+
+/**
+ * Locks an entity.
+ *
+ * @param entity Entity index.
+ * @noreturn
+ */
+stock Entity_Lock(entity)
+{
+ SetEntProp(entity, Prop_Data, "m_bLocked", 1, 1);
+}
+/**
+ * Unlocks an entity.
+ *
+ * @param entity Entity index.
+ * @noreturn
+ */
+stock Entity_UnLock(entity)
+{
+ SetEntProp(entity, Prop_Data, "m_bLocked", 0, 1);
+}
+
+/**
+ * Gets the health of an entity.
+ *
+ * @param entity entity index.
+ * @return current health points
+ */
+stock Entity_GetHealth(entity)
+{
+ return GetEntProp(entity, Prop_Data, "m_iHealth");
+}
+
+/**
+ * Sets the health of an entity.
+ *
+ * @param entity entity index.
+ * @param value health to set (anything above 511 will overload)
+ * @noreturn
+ */
+stock Entity_SetHealth(entity, value, ignoreMax=false, kill=true)
+{
+ new health = value;
+
+ if (!ignoreMax) {
+ new maxHealth = Entity_GetMaxHealth(entity);
+
+ if (health > maxHealth) {
+ health = maxHealth;
+ }
+ }
+
+ if (health < 0) {
+ health = 0;
+ }
+
+ SetEntProp(entity, Prop_Data, "m_iHealth", health);
+
+ if (health <= 0) {
+ Entity_Kill(entity);
+ }
+
+ return health;
+}
+
+/**
+ * Add health to an entity
+ *
+ * @param entity entity index
+ * @param value health to add
+ * @return returns the new health value set
+ */
+stock Entity_AddHealth(entity, value, ignoreMax=false, kill=true)
+{
+ new health = Entity_GetHealth(entity);
+
+ health += value;
+
+ return Entity_SetHealth(entity, health, ignoreMax, kill);
+}
+
+/**
+ * Takes health from an entity
+ *
+ * @param entity entity index
+ * @param value health to add
+ * @return returns the new health value set
+ */
+stock Entity_TakeHealth(entity, value, ignoreMax=false, kill=true)
+{
+ new health = Entity_GetHealth(entity);
+
+ health -= value;
+
+ return Entity_SetHealth(entity, health, ignoreMax, kill);
+}
+
+/**
+ * Get the max health of an entity
+ *
+ * @param entity Entity Index
+ * @return Max health points
+ */
+stock Entity_GetMaxHealth(entity)
+{
+ return GetEntProp(entity, Prop_Data, "m_iMaxHealth");
+}
+
+
+/**
+ * Set the max health of an entity.
+ *
+ * @param entity Entity index
+ * @param value Max health to set (anything above 511 will overload)
+ * @noreturn
+ */
+stock Entity_SetMaxHealth(entity, value)
+{
+ SetEntProp(entity, Prop_Data, "m_iMaxHealth", value);
+ return value;
+}
+
+/**
+ * Returns the Float distance between an entity
+ * and a vector origin.
+ *
+ * @param entity Entity Index.
+ * @param target Vector Origin.
+ * @return Distance Float value.
+ */
+stock Float:Entity_GetDistanceOrigin(entity, const Float:vec[3])
+{
+ new Float:entityVec[3];
+ Entity_GetAbsOrigin(entity, entityVec);
+
+ return GetVectorDistance(entityVec, vec);
+}
+
+/**
+ * Returns the Float distance between two entities.
+ * Both entities must be valid.
+ *
+ * @param entity Entity Index.
+ * @param target Target Entity Index.
+ * @return Distance Float value.
+ */
+stock Float:Entity_GetDistance(entity, target)
+{
+ new Float:targetVec[3];
+ Entity_GetAbsOrigin(target, targetVec);
+
+ return Entity_GetDistanceOrigin(entity, targetVec);
+}
+
+/**
+ * Checks if the given 2 entitys are within a given range.
+ *
+ * @param entity Entity Index.
+ * @param target Target Entity Index.
+ * @param distance Max Float distance.
+ * @return True if the given entities are closer than the given distance value, false otherwise.
+ */
+stock bool:Entity_InRange(entity, target, Float:distance)
+{
+ if (Entity_GetDistance(entity, target) > distance) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Enables the motion of an entity.
+ *
+ * @param entity Entity index.
+ * @return True on success, false otherwise
+ */
+stock bool:Entity_EnableMotion(entity)
+{
+ return AcceptEntityInput(entity, "enablemotion");
+}
+
+/**
+ * Disables the motion of an entity.
+ *
+ * @param entity Entity index.
+ * @return True on success, false otherwise
+ */
+stock bool:Entity_DisableMotion(entity)
+{
+ return AcceptEntityInput(entity, "disablemotion");
+}
+
+/**
+ * Freezes an entity by setting the FL_FROZEN flag.
+ *
+ * @param entity Entity index.
+ * @return True on success, false otherwise
+ */
+stock Entity_Freeze(entity)
+{
+ Entity_AddFlags(entity, FL_FROZEN);
+}
+
+/**
+ * Unfreezes an entity by removing the FL_FROZEN flag.
+ *
+ * @param entity Entity index.
+ * @return True on success, false otherwise
+ */
+stock Entity_UnFreeze(entity)
+{
+ Entity_RemoveFlags(entity, FL_FROZEN);
+}
+
+
+/**
+ * This function points an entity to another with the targetname
+ * and name. Useful for allot of entities like trigger_teleport.
+ * If the name is not specified it will be generated automatically.
+ *
+ * @param entity Entity index.
+ * @param target Target entity index.
+ * @param Optional: target name
+ * @noreturn
+ */
+stock Entity_PointAtTarget(entity, target, const String:name[]="")
+{
+ decl String:targetName[128];
+ Entity_GetTargetName(entity, targetName, sizeof(targetName));
+
+ if (name[0] == '\0') {
+
+ if (targetName[0] == '\0') {
+ // Let's generate our own name
+ Format(
+ targetName,
+ sizeof(targetName),
+ "_smlib_Entity_PointAtTarget:%d",
+ target
+ );
+ }
+ }
+ else {
+ strcopy(targetName, sizeof(targetName), name);
+ }
+
+ Entity_SetTargetName(entity, targetName);
+ Entity_SetName(target, targetName);
+}
+
+/**
+ * This function points a point_hurt entity to another damage target entity..
+ * and name. Useful for allot of entities like trigger_teleport.
+ * If the name is not specified it will be generated automatically.
+ *
+ * @param entity Entity index.
+ * @param target Target entity index.
+ * @param Optional: target name
+ * @noreturn
+ */
+stock Entity_PointHurtAtTarget(entity, target, const String:name[]="")
+{
+ decl String:targetName[128];
+ Entity_GetTargetName(entity, targetName, sizeof(targetName));
+
+ if (name[0] == '\0') {
+
+ if (targetName[0] == '\0') {
+ // Let's generate our own name
+ Format(
+ targetName,
+ sizeof(targetName),
+ "_smlib_Entity_PointHurtAtTarget:%d",
+ target
+ );
+ }
+ }
+ else {
+ strcopy(targetName, sizeof(targetName), name);
+ }
+
+ DispatchKeyValue(entity, "DamageTarget", targetName);
+ Entity_SetName(target, targetName);
+}
+
+/**
+ * Checks if an entity is a player or not.
+ * No checks are done if the entity is actually valid,
+ * the player is connected or ingame.
+ *
+ * @param entity Entity index.
+ * @return True if the entity is a player, false otherwise.
+ */
+stock bool:Entity_IsPlayer(entity)
+{
+ if (entity < 1 || entity > MaxClients) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Creates an entity by classname.
+ *
+ * @param className Classname String.
+ * @param ForceEdictIndex Edict Index to use.
+ * @return Entity Index or INVALID_ENT_REFERENCE if the slot is already in use.
+ */
+stock Entity_Create(const String:className[], ForceEdictIndex=-1)
+{
+ if (ForceEdictIndex != -1 && Entity_IsValid(ForceEdictIndex)) {
+ return INVALID_ENT_REFERENCE;
+ }
+
+ return CreateEntityByName(className, ForceEdictIndex);
+}
+
+/**
+ * Kills an entity on the next frame (delayed).
+ * It is safe to use with entity loops.
+ * If the entity is is player ForcePlayerSuicide() is called.
+ *
+ * @param kenny Entity index.
+ * @param killChildren When true, kennys children are killed too.
+ * @return True on success, false otherwise.
+ */
+stock bool:Entity_Kill(kenny, killChildren=false)
+{
+ if (Entity_IsPlayer(kenny)) {
+ // Oh My God! They Killed Kenny!!
+ ForcePlayerSuicide(kenny);
+ return true;
+ }
+
+ if(killChildren){
+ return AcceptEntityInput(kenny, "KillHierarchy");
+ }
+ else {
+ return AcceptEntityInput(kenny, "Kill");
+ }
+}
+
+/**
+ * Kills all entities with the given networked classname.
+ * It is safe to use with entity loops.
+ * If the entity is is player ForcePlayerSuicide() is called.
+ *
+ * @param className Entity Network Class to search for.
+ * @return Number of entities killed.
+ */
+stock Entity_KillAllByClassName(const String:className[])
+{
+ new x = 0;
+
+ new entity = INVALID_ENT_REFERENCE;
+ while ((entity = FindEntityByClassname(entity, className)) != INVALID_ENT_REFERENCE) {
+ AcceptEntityInput(entity, "kill");
+ x++;
+ }
+
+ return x;
+}
+
+/**
+ * Gets the owner of an entity.
+ * For example the owner of a weapon entity.
+ *
+ * @param entity Entity index.
+ * @return Ground Entity or -1
+ */
+stock Entity_GetOwner(entity)
+{
+ return GetEntPropEnt(entity, Prop_Data, "m_hOwnerEntity");
+}
+
+/**
+ * Sets the owner of an entity.
+ * For example the owner of a weapon entity.
+ *
+ * @param entity Entity index.
+ * @noreturn
+ */
+stock Entity_SetOwner(entity, newOwner)
+{
+ SetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity", newOwner);
+}
+
+/**
+ * Get's the ground entity this entity stands on.
+ *
+ * @param entity Entity index.
+ * @return Ground Entity or -1
+ */
+stock Entity_GetGroundEntity(entity)
+{
+ return GetEntPropEnt(entity, Prop_Data, "m_hGroundEntity");
+}
+
+/*
+ * Damage definitions
+ */
+
+#if !defined DMG_GENERIC
+
+#define DMG_GENERIC 0 // generic damage was done
+#define DMG_CRUSH (1 << 0) // crushed by falling or moving object.
+ // NOTE: It's assumed crush damage is occurring as a result of physics collision, so no extra physics force is generated by crush damage.
+ // DON'T use DMG_CRUSH when damaging entities unless it's the result of a physics collision. You probably want DMG_CLUB instead.
+#define DMG_BULLET (1 << 1) // shot
+#define DMG_SLASH (1 << 2) // cut, clawed, stabbed
+#define DMG_BURN (1 << 3) // heat burned
+#define DMG_VEHICLE (1 << 4) // hit by a vehicle
+#define DMG_FALL (1 << 5) // fell too far
+#define DMG_BLAST (1 << 6) // explosive blast damage
+#define DMG_CLUB (1 << 7) // crowbar, punch, headbutt
+#define DMG_SHOCK (1 << 8) // electric shock
+#define DMG_SONIC (1 << 9) // sound pulse shockwave
+#define DMG_ENERGYBEAM (1 << 10) // laser or other high energy beam
+#define DMG_PREVENT_PHYSICS_FORCE (1 << 11) // Prevent a physics force
+#define DMG_NEVERGIB (1 << 12) // with this bit OR'd in, no damage type will be able to gib victims upon death
+#define DMG_ALWAYSGIB (1 << 13) // with this bit OR'd in, any damage type can be made to gib victims upon death.
+#define DMG_DROWN (1 << 14) // Drowning
+
+
+#define DMG_PARALYZE (1 << 15) // slows affected creature down
+#define DMG_NERVEGAS (1 << 16) // nerve toxins, very bad
+#define DMG_POISON (1 << 17) // blood poisoning - heals over time like drowning damage
+#define DMG_RADIATION (1 << 18) // radiation exposure
+#define DMG_DROWNRECOVER (1 << 19) // drowning recovery
+#define DMG_ACID (1 << 20) // toxic chemicals or acid burns
+#define DMG_SLOWBURN (1 << 21) // in an oven
+
+#define DMG_REMOVENORAGDOLL (1<<22) // with this bit OR'd in, no ragdoll will be created, and the target will be quietly removed.
+ // use this to kill an entity that you've already got a server-side ragdoll for
+
+#define DMG_PHYSGUN (1<<23) // Hit by manipulator. Usually doesn't do any damage.
+#define DMG_PLASMA (1<<24) // Shot by Cremator
+#define DMG_AIRBOAT (1<<25) // Hit by the airboat's gun
+
+#define DMG_DISSOLVE (1<<26) // Dissolving!
+#define DMG_BLAST_SURFACE (1<<27) // A blast on the surface of water that cannot harm things underwater
+#define DMG_DIRECT (1<<28)
+#define DMG_BUCKSHOT (1<<29) // not quite a bullet. Little, rounder, different.
+
+#endif
+
+/**
+ * Does damage to an entity.
+ * This is a powerful function that allows you to specify
+ * who the attacker is, the damage type and also what weapon
+ * should be displayed in the hud kill message.
+ * Note that for entities that fire another entity (RPG's, Crossbow's,
+ * you have to pass the bullet's class, not the weapon's class !
+ * It hasn't been tested how expensive this function is, as it
+ * uses the entity point_hurt.
+ * If you need a cheaper function use Entity_RemoveHealth().
+ *
+ * @param entity Entity index.
+ * @param damage Amount of damage.
+ * @param attacker Entity Index of the attacker.
+ * @param damageType Use the DMG_ definations.
+ * @param fakeClassName Classname to fake, you can set this if you
+ * want a specific weapon to be shown in the HUD kill message.
+ * @return True on success, false otherwise.
+ */
+stock bool:Entity_Hurt(entity, damage, attacker=0, damageType=DMG_GENERIC, const String:fakeClassName[]="")
+{
+ static point_hurt = INVALID_ENT_REFERENCE;
+
+ if (point_hurt == INVALID_ENT_REFERENCE || !IsValidEntity(point_hurt)) {
+ point_hurt = EntIndexToEntRef(Entity_Create("point_hurt"));
+
+ if (point_hurt == INVALID_ENT_REFERENCE) {
+ return false;
+ }
+
+ DispatchSpawn(point_hurt);
+ }
+
+ AcceptEntityInput(point_hurt, "TurnOn");
+ SetEntProp(point_hurt, Prop_Data, "m_nDamage", damage);
+ SetEntProp(point_hurt, Prop_Data, "m_bitsDamageType", damageType);
+ Entity_PointHurtAtTarget(point_hurt, entity);
+
+ if (fakeClassName[0] != '\0') {
+ Entity_SetClassName(point_hurt, fakeClassName);
+ }
+
+ AcceptEntityInput(point_hurt, "Hurt", attacker);
+ AcceptEntityInput(point_hurt, "TurnOff");
+
+ if (fakeClassName[0] != '\0') {
+ Entity_SetClassName(point_hurt, "point_hurt");
+ }
+
+ return true;
+}
+
+/*
+ * Gets the parent entity of an entity.
+ *
+ * @param entity Entity Index.
+ * @return Entity Index of the parent.
+ */
+stock Entity_GetParent(entity)
+{
+ return GetEntPropEnt(entity, Prop_Data, "m_pParent");
+}
+
+/*
+ * Clears the parent of an entity.
+ *
+ * @param entity Entity Index.
+ * @noreturn
+ */
+stock Entity_ClearParent(entity)
+{
+ SetVariantString("");
+ AcceptEntityInput(entity, "ClearParent");
+}
+
+/*
+ * Sets the parent entity of an entity.
+ *
+ * @param entity Entity Index.
+ * @param parentEntity Entity Index of the new parent.
+ * @noreturn
+ */
+stock Entity_SetParent(entity, parent)
+{
+ SetVariantString("!activator");
+ AcceptEntityInput(entity, "SetParent", parent);
+}
+
+
+/*
+ * Callback for Change_OverTime.
+ * Note that every parameter is a reference and can be changed during this callback.
+ * You can get the elapsed time since start by multiply tick with currentCall.
+ *
+ * @param entity Entity Index.
+ * @param interval The current interval from the current game time to execute the next call of this function.
+ * @param currentCall The current call number (0 is the 1st call at 0.0 seconds, 1 the 2nd call at tick*1 seconds, ...).
+ * @return When true this callback will be called again at the next defined tick, otherwise it won't.
+ */
+functag Entity_ChangeOverTimeCallback bool:public(&entity, &Float:interval, &currentCall);
+
+/*
+ * Creates a timer and provides a callback to change various things about an entity over time.
+ *
+ * @param entity Entity Index.
+ * @param interval Interval from the current game time to execute the given function.
+ * @noreturn
+ */
+stock Entity_ChangeOverTime(entity, Float:interval=0.1, Entity_ChangeOverTimeCallback:valueCallback)
+{
+ new Handle:dataPack = CreateDataPack();
+ WritePackCell(dataPack, EntIndexToEntRef(entity));
+ WritePackFloat(dataPack, interval);
+ WritePackCell(dataPack, 0);
+#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7
+ WritePackFunction(dataPack, valueCallback);
+#else
+ WritePackCell(dataPack, _:valueCallback);
+#endif
+ ResetPack(dataPack);
+ __smlib_Timer_ChangeOverTime(INVALID_HANDLE,dataPack);
+}
+
+public Action:__smlib_Timer_ChangeOverTime(Handle:Timer, Handle:dataPack)
+{
+ new entity = EntRefToEntIndex(ReadPackCell(dataPack));
+ if(!Entity_IsValid(entity)){
+ return Plugin_Stop;
+ }
+
+ new Float:interval = ReadPackFloat(dataPack);
+ new currentCall = ReadPackCell(dataPack);
+#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7
+ new Function:callback = ReadPackFunction(dataPack);
+#else
+ new Function:callback = Function:ReadPackCell(dataPack);
+#endif
+
+ new any:result;
+ Call_StartFunction(INVALID_HANDLE, callback);
+ Call_PushCellRef(entity);
+ Call_PushFloatRef(interval);
+ Call_PushCellRef(currentCall);
+ Call_Finish(result);
+
+ if(result == false){
+ return Plugin_Stop;
+ }
+
+ ResetPack(dataPack,true);
+ WritePackCell(dataPack, EntIndexToEntRef(entity));
+ WritePackFloat(dataPack, interval);
+ WritePackCell(dataPack, currentCall+1);
+#if SOURCEMOD_V_MAJOR >= 1 && SOURCEMOD_V_MINOR >= 7
+ WritePackFunction(dataPack, callback);
+#else
+ WritePackCell(dataPack, _:callback);
+#endif
+ ResetPack(dataPack);
+ CreateTimer(interval,__smlib_Timer_ChangeOverTime,dataPack);
+ return Plugin_Stop;
+}
+
+
+/**
+ * Gets the next child, entity is parent of.
+ *
+ * @param client Entity Index (of Parent)
+ * @param start Start Index.
+ * @return Entity Index or -1 if no entity was found.
+ */
+stock Entity_GetNextChild(parent, start=0)
+{
+ for (new entity=start; entity <= 2048; entity++) {
+
+ if (!Entity_IsValid(entity)) {
+ continue;
+ }
+
+ if (entity > 0 && entity <= MaxClients && !IsClientConnected(entity)) {
+ continue;
+ }
+
+ if (Entity_GetParent(entity) == parent) {
+ return entity;
+ }
+ }
+
+ return INVALID_ENT_REFERENCE;
+}
+/**
+ * Gets the move/open direction of an entity (only available for func_door*, prop_door* and func_movelinear).
+ * Ex: if vec[2] is 1.0 a func_door moves straight up.
+ *
+ * @param entity Entity index.
+ * @param vec Vector.
+ * @noreturn
+ */
+stock Entity_GetMoveDirection(entity, Float:vec[3])
+{
+ GetEntPropVector(entity, Prop_Data, "m_vecMoveDir", vec);
+}
+/**
+ * Sets the move/open direction of an entity (only available for func_door*, prop_door* and func_movelinear).
+ * Ex: if vec[2] is 1.0 a func_door moves straight up.
+ *
+ * @param entity Entity index.
+ * @param vec Vector.
+ * @noreturn
+ */
+stock Entity_SetMoveDirection(entity, const Float:vec[3])
+{
+ SetEntPropVector(entity, Prop_Data, "m_vecMoveDir", vec);
+}
+
+/**
+ * Returns if the entity will force close (won't be blockable by players and/or objects) or not when triggered to move.
+ *
+ * @param entity Entity index.
+ * @return True if the door will force close, otherwise false.
+ */
+stock bool:Entity_GetForceClose(entity)
+{
+ return bool:GetEntProp(entity, Prop_Data, "m_bForceClosed");
+}
+
+/**
+ * Sets if the door should force close (souldn't be blockable by players and/or objects) or not when triggered to move.
+ *
+ * @param entity Entity index.
+ * @param forceClose If true the door will force close, otherwise it won't.
+ * @noreturn
+ */
+stock Entity_SetForceClose(entity, bool:forceClose)
+{
+ SetEntProp(entity, Prop_Data, "m_bForceClosed", forceClose);
+}
+
+/**
+ * Gets the speed of a moving entity (like doors: open close speed).
+ *
+ * @param entity Entity index.
+ * @return Speed of the entity.
+ */
+stock Float:Entity_GetSpeed(entity)
+{
+ return GetEntPropFloat(entity, Prop_Data, "m_flSpeed");
+}
+
+/**
+ * Sets how fast an entity moves (like doors: open close speed).
+ *
+ * @param entity Entity index.
+ * @param speed The new speed of the entity.
+ * @noreturn
+ */
+stock Entity_SetSpeed(entity, Float:speed)
+{
+ SetEntPropFloat(entity, Prop_Data, "m_flSpeed", speed);
+}
+
+/**
+ * Gets the damage of a moving entity when blocked (like doors when open or close and players and/or objects are between the entity and something else).
+ * Note: Negative values add health to the blocking entity.
+ *
+ * @param entity Entity index.
+ * @return Damage.
+ */
+stock Float:Entity_GetBlockDamage(entity)
+{
+ return GetEntPropFloat(entity, Prop_Data, "m_flBlockDamage");
+}
+
+/**
+ * Sets the damage of a moving entity when blocked (like doors when open or close and players and/or objects are between the entity and something else).
+ * Note: Negative values add health to the blocking entity.
+ *
+ * @param entity Entity index.
+ * @param damage Damage.
+ * @noreturn
+ */
+stock Entity_SetBlockDamage(entity, Float:damage)
+{
+ SetEntPropFloat(entity, Prop_Data, "m_flBlockDamage", damage);
+}
+
+/**
+ * Returns if the given entity is disabled or not.
+ *
+ * @param entity Entity index.
+ * @return True if entity is disabled, otherwise false.
+ */
+stock bool:Entity_IsDisabled(entity)
+{
+ return bool:GetEntProp(entity, Prop_Data, "m_bDisabled", 1);
+}
+
+/**
+ * Disables the given entity.
+ *
+ * @param entity Entity index.
+ * @return True if successful otherwise false.
+ */
+stock Entity_Disable(entity)
+{
+ return AcceptEntityInput(entity, "Disable");
+}
+
+/**
+ * Enables the given entity.
+ *
+ * @param entity Entity index.
+ * @return True if successful otherwise false.
+ */
+stock Entity_Enable(entity)
+{
+ return AcceptEntityInput(entity, "Enable");
+}
+
+
+// settings for m_takedamage taken from hl2sdk-ob-valve\game\shared\shareddefs.h
+#define DAMAGE_NO 0
+#define DAMAGE_EVENTS_ONLY 1 // Call damage functions, but don't modify health
+#define DAMAGE_YES 2
+#define DAMAGE_AIM 3
+
+/**
+ * Sets the mode for an entity to take damage.
+ * Note: This is used to give a client god mode (DAMAGE_NO).
+ *
+ * @param entity Entity index.
+ * @param value Mode, use DAMAGE_* defines.
+ * @noreturn
+ */
+stock Entity_SetTakeDamage(entity, value)
+{
+ SetEntProp(entity, Prop_Data, "m_takedamage", value, 1);
+}
+
+/**
+ * Gets the mode for an entity to take damage.
+ * Note: When the return value is DAMAGE_NO then the client is using godmode.
+ *
+ * @param entity Entity index.
+ * @return Take damage mode (DAMAGE_*).
+ */
+stock Entity_GetTakeDamage(entity)
+{
+ return GetEntProp(entity, Prop_Data, "m_takedamage", 1);
+}
+
+/**
+ * Sets the minimum of damage required to hurt this entity.
+ * Example: This is used to block any damage done by projectile weapons against a gun ship in Half-Life 2.
+ *
+ * @param entity Entity index.
+ * @param minDamage Minimum required damage.
+ * @noreturn
+ */
+stock Entity_SetMinHealthDamage(entity, minDamage)
+{
+ SetEntProp(entity, Prop_Data, "m_iMinHealthDmg", minDamage);
+}
+
+/**
+ * Gets the minimum of damage required to hurt this entity.
+ * Example: This is used to block any damage done by projectile weapons against a gun ship in Half-Life 2.
+ *
+ * @param entity Entity index.
+ * @return Minimum required damage.
+ */
+stock Entity_GetMinHealthDamage(entity)
+{
+ return GetEntProp(entity, Prop_Data, "m_iMinHealthDmg");
+}
+
+/**
+ * Gets an entity's color.
+ *
+ * @param entity Entity index
+ * @param color 4 dimensional array where [r,g,b,a] values are stored
+ * @noreturn
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+stock Entity_GetRenderColor(entity, color[4])
+{
+ static bool:gotconfig = false;
+ static String:prop[32];
+
+ if (!gotconfig) {
+ new Handle:gc = LoadGameConfigFile("core.games");
+ new bool:exists = GameConfGetKeyValue(gc, "m_clrRender", prop, sizeof(prop));
+ CloseHandle(gc);
+
+ if (!exists) {
+ strcopy(prop, sizeof(prop), "m_clrRender");
+ }
+
+ gotconfig = true;
+ }
+
+ new offset = GetEntSendPropOffs(entity, prop);
+
+ if (offset <= 0) {
+ ThrowError("SetEntityRenderColor not supported by this mod");
+ }
+
+ for (new i=0; i < 4; i++) {
+ color[i] = GetEntData(entity, offset + i + 1, 1);
+ }
+}
+
+/**
+ * Sets an entity's color.
+ * Doesn't change the value, if set to -1.
+ *
+ * @param entity Entity index
+ * @param r Amount of red (0-255)
+ * @param g Amount of green (0-255)
+ * @param b Amount of blue (0-255)
+ * @param a Amount of alpha (0-255)
+ * @noreturn
+ * @error Invalid entity index, or lack of mod compliance.
+ */
+stock Entity_SetRenderColor(entity, r=-1, g=-1, b=-1, a=-1)
+{
+ static bool:gotconfig = false;
+ static String:prop[32];
+
+ if (!gotconfig) {
+ new Handle:gc = LoadGameConfigFile("core.games");
+ new bool:exists = GameConfGetKeyValue(gc, "m_clrRender", prop, sizeof(prop));
+ CloseHandle(gc);
+
+ if (!exists) {
+ strcopy(prop, sizeof(prop), "m_clrRender");
+ }
+
+ gotconfig = true;
+ }
+
+ new offset = GetEntSendPropOffs(entity, prop);
+
+ if (offset <= 0) {
+ ThrowError("SetEntityRenderColor not supported by this mod");
+ }
+
+ if(r != -1) {
+ SetEntData(entity, offset, r, 1, true);
+ }
+
+ if(g != -1) {
+ SetEntData(entity, offset + 1, g, 1, true);
+ }
+
+ if(b != -1) {
+ SetEntData(entity, offset + 2, b, 1, true);
+ }
+
+ if(a != -1) {
+ SetEntData(entity, offset + 3, a, 1, true);
+ }
+}
+
+/**
+ * Sends the 'addouput' command to an entity.
+ *
+ * @param entity Entity Index.
+ * @param input Input command.
+ * @param activator Entity index which initiated the sequence of actions (-1 for a NULL entity).
+ * @param caller Entity index from which this event is sent (-1 for a NULL entity).
+ * @param outputid Unknown.
+ * @return True if successful, otherwise false.
+ */
+stock bool:Entity_AddOutput(entity, const String:input[], activator=-1, caller=-1, outputid=0)
+{
+ SetVariantString(input);
+ return AcceptEntityInput(entity, "addoutput", activator, caller, outputid);
+}
+
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/files.inc b/sourcemod-1.5-dev/scripting/include/smlib/files.inc
new file mode 100644
index 0000000..3fda876
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/files.inc
@@ -0,0 +1,458 @@
+#if defined _smlib_files_included
+ #endinput
+#endif
+#define _smlib_files_included
+
+#include <sourcemod>
+#include <sdktools>
+#include <smlib/arrays>
+
+/**
+ * Gets the Base name of a path.
+ * Examples:
+ * blub.txt -> "blub.txt"
+ * /sourcemod/extensions/example.ext.so -> "example.ext.so"
+ *
+ * @param path File path
+ * @param buffer String buffer array
+ * @param size Size of string buffer
+ * @noreturn
+ */
+stock bool:File_GetBaseName(const String:path[], String:buffer[], size)
+{
+ if (path[0] == '\0') {
+ buffer[0] = '\0';
+ return;
+ }
+
+ new pos_start = FindCharInString(path, '/', true);
+
+ if (pos_start == -1) {
+ pos_start = FindCharInString(path, '\\', true);
+ }
+
+ pos_start++;
+
+ strcopy(buffer, size, path[pos_start]);
+}
+
+/**
+ * Gets the Directory of a path (without the file name).
+ * Does not work with "." as the path.
+ * Examples:
+ * blub.txt -> "blub.txt"
+ * /sourcemod/extensions/example.ext.so -> "example.ext.so"
+ *
+ * @param path File path
+ * @param buffer String buffer array
+ * @param size Size of string buffer
+ * @noreturn
+ */
+stock bool:File_GetDirName(const String:path[], String:buffer[], size)
+{
+ if (path[0] == '\0') {
+ buffer[0] = '\0';
+ return;
+ }
+
+ new pos_start = FindCharInString(path, '/', true);
+
+ if (pos_start == -1) {
+ pos_start = FindCharInString(path, '\\', true);
+
+ if (pos_start == -1) {
+ buffer[0] = '\0';
+ return;
+ }
+ }
+
+ strcopy(buffer, size, path);
+ buffer[pos_start] = '\0';
+}
+
+/**
+ * Gets the File name of a path.
+ * blub.txt -> "blub"
+ * /sourcemod/extensions/example.ext.so -> "example.ext"
+ *
+ * @param path File path
+ * @param buffer String buffer array
+ * @param size Size of string buffer
+ * @noreturn
+ */
+stock bool:File_GetFileName(const String:path[], String:buffer[], size)
+{
+ if (path[0] == '\0') {
+ buffer[0] = '\0';
+ return;
+ }
+
+ File_GetBaseName(path, buffer, size);
+
+ new pos_ext = FindCharInString(buffer, '.', true);
+
+ if (pos_ext != -1) {
+ buffer[pos_ext] = '\0';
+ }
+}
+
+/**
+ * Gets the Extension of a file.
+ * Examples:
+ * blub.inc.txt -> "txt"
+ * /sourcemod/extensions/example.ext.so -> "so"
+ *
+ * @param path Path String
+ * @param buffer String buffer array
+ * @param size Max length of string buffer
+ * @noreturn
+ */
+stock File_GetExtension(const String:path[], String:buffer[], size)
+{
+ new extpos = FindCharInString(path, '.', true);
+
+ if (extpos == -1) {
+ buffer[0] = '\0';
+ return;
+ }
+
+ strcopy(buffer, size, path[++extpos]);
+}
+
+/**
+ * Adds a path to the downloadables network string table.
+ * This can be a file or directory and also works recursed.
+ * You can optionally specify file extensions that should be ignored.
+ * Bz2 and ztmp are automatically ignored.
+ * It only adds files that actually exist.
+ * You can also specify a wildcard * after the ., very useful for models.
+ * This forces a client to download the file if they do not already have it.
+ *
+ * @param path Path String
+ * @param recursive Whether to do recursion or not.
+ * @param ignoreExts Optional: 2 dimensional String array.You can define it like this: new String:ignore[][] = { ".ext1", ".ext2" };
+ * @param size This should be set to the number of file extensions in the ignoreExts array (sizeof(ignore) for the example above)
+ * @noreturn
+ */
+
+// Damn you SourcePawn :( I didn't want to
+new String:_smlib_empty_twodimstring_array[][] = { { '\0' } };
+stock File_AddToDownloadsTable(const String:path[], bool:recursive=true, const String:ignoreExts[][]=_smlib_empty_twodimstring_array, size=0)
+{
+ if (path[0] == '\0') {
+ return;
+ }
+
+ if (FileExists(path)) {
+
+ new String:fileExtension[5];
+ File_GetExtension(path, fileExtension, sizeof(fileExtension));
+
+ if (StrEqual(fileExtension, "bz2", false) || StrEqual(fileExtension, "ztmp", false)) {
+ return;
+ }
+
+ if (Array_FindString(ignoreExts, size, fileExtension) != -1) {
+ return;
+ }
+
+ decl String:path_new[PLATFORM_MAX_PATH];
+ strcopy(path_new, sizeof(path_new), path);
+ ReplaceString(path_new, sizeof(path_new), "//", "/");
+
+ AddFileToDownloadsTable(path_new);
+ }
+ else if (recursive && DirExists(path)) {
+
+ decl String:dirEntry[PLATFORM_MAX_PATH];
+ new Handle:__dir = OpenDirectory(path);
+
+ while (ReadDirEntry(__dir, dirEntry, sizeof(dirEntry))) {
+
+ if (StrEqual(dirEntry, ".") || StrEqual(dirEntry, "..")) {
+ continue;
+ }
+
+ Format(dirEntry, sizeof(dirEntry), "%s/%s", path, dirEntry);
+ File_AddToDownloadsTable(dirEntry, recursive, ignoreExts, size);
+ }
+
+ CloseHandle(__dir);
+ }
+ else if (FindCharInString(path, '*', true)) {
+
+ new String:fileExtension[4];
+ File_GetExtension(path, fileExtension, sizeof(fileExtension));
+
+ if (StrEqual(fileExtension, "*")) {
+
+ decl
+ String:dirName[PLATFORM_MAX_PATH],
+ String:fileName[PLATFORM_MAX_PATH],
+ String:dirEntry[PLATFORM_MAX_PATH];
+
+ File_GetDirName(path, dirName, sizeof(dirName));
+ File_GetFileName(path, fileName, sizeof(fileName));
+ StrCat(fileName, sizeof(fileName), ".");
+
+ new Handle:__dir = OpenDirectory(dirName);
+ while (ReadDirEntry(__dir, dirEntry, sizeof(dirEntry))) {
+
+ if (StrEqual(dirEntry, ".") || StrEqual(dirEntry, "..")) {
+ continue;
+ }
+
+ if (strncmp(dirEntry, fileName, strlen(fileName)) == 0) {
+ Format(dirEntry, sizeof(dirEntry), "%s/%s", dirName, dirEntry);
+ File_AddToDownloadsTable(dirEntry, recursive, ignoreExts, size);
+ }
+ }
+
+ CloseHandle(__dir);
+ }
+ }
+
+ return;
+}
+
+
+/*
+ * Adds all files/paths in the given text file to the download table.
+ * Recursive mode enabled, see File_AddToDownloadsTable()
+ * Comments are allowed ! Supported comment types are ; // #
+ *
+ * @param path Path to the .txt file.
+ * @noreturn
+ */
+stock File_ReadDownloadList(const String:path[])
+{
+ new Handle:file = OpenFile(path, "r");
+
+ if (file == INVALID_HANDLE) {
+ return;
+ }
+
+ new String:buffer[PLATFORM_MAX_PATH];
+ while (!IsEndOfFile(file)) {
+ ReadFileLine(file, buffer, sizeof(buffer));
+
+ new pos;
+ pos = StrContains(buffer, "//");
+ if (pos != -1) {
+ buffer[pos] = '\0';
+ }
+
+ pos = StrContains(buffer, "#");
+ if (pos != -1) {
+ buffer[pos] = '\0';
+ }
+
+ pos = StrContains(buffer, ";");
+ if (pos != -1) {
+ buffer[pos] = '\0';
+ }
+
+ TrimString(buffer);
+
+ if (buffer[0] == '\0') {
+ continue;
+ }
+
+ File_AddToDownloadsTable(buffer);
+ }
+
+ CloseHandle(file);
+}
+
+/*
+ * Attempts to load a translation file and optionally unloads the plugin if the file
+ * doesn't exist (also prints an error message).
+ *
+ * @param file Filename of the translations file (eg. <pluginname>.phrases).
+ * @param setFailState If true, it sets the failstate if the translations file doesn't exist
+ * @return True on success, false otherwise (only if setFailState is set to false)
+ */
+stock File_LoadTranslations(const String:file[], setFailState=true)
+{
+ decl String:path[PLATFORM_MAX_PATH];
+
+ BuildPath(Path_SM, path, sizeof(path), "translations/%s", file);
+
+ if (FileExists(path)) {
+ LoadTranslations(file);
+ return true;
+ }
+
+ Format(path,sizeof(path), "%s.txt", path);
+
+ if (!FileExists(path)) {
+
+ if (setFailState) {
+ SetFailState("Unable to locate translation file (%s).", path);
+ }
+
+ return false;
+ }
+
+ LoadTranslations(file);
+
+ return true;
+}
+
+/*
+ * Reads the contents of a given file into a string buffer in binary mode.
+ *
+ * @param path Path to the file
+ * @param buffer String buffer
+ * @param size If -1, reads until a null terminator is encountered in the file. Otherwise, read_count bytes are read into the buffer provided. In this case the buffer is not explicitly null terminated, and the buffer will contain any null terminators read from the file.
+ * @return Number of characters written to the buffer, or -1 if an error was encountered.
+ */
+stock File_ToString(const String:path[], String:buffer[], size)
+{
+ new Handle:file = OpenFile(path, "rb");
+
+ if (file == INVALID_HANDLE) {
+ buffer[0] = '\0';
+ return -1;
+ }
+
+ new num_bytes_written = ReadFileString(file, buffer, size);
+ CloseHandle(file);
+
+ return num_bytes_written;
+}
+
+/*
+ * Writes a string into a file in binary mode.
+ *
+ * @param file Path to the file
+ * @param str String to write
+ * @return True on success, false otherwise
+ */
+stock bool:File_StringToFile(const String:path[], String:str[])
+{
+ new Handle:file = OpenFile(path, "wb");
+
+ if (file == INVALID_HANDLE) {
+ return false;
+ }
+
+ new bool:success = WriteFileString(file, str, false);
+ CloseHandle(file);
+
+ return success;
+}
+
+/*
+ * Copies file source to destination
+ * Based on code of javalia:
+ * http://forums.alliedmods.net/showthread.php?t=159895
+ *
+ * @param source Input file
+ * @param destination Output file
+ */
+stock bool:File_Copy(const String:source[], const String:destination[])
+{
+ new Handle:file_source = OpenFile(source, "rb");
+
+ if (file_source == INVALID_HANDLE) {
+ return false;
+ }
+
+ new Handle:file_destination = OpenFile(destination, "wb");
+
+ if (file_destination == INVALID_HANDLE) {
+ CloseHandle(file_source);
+ return false;
+ }
+
+ new buffer[32];
+ new cache;
+
+ while (!IsEndOfFile(file_source)) {
+ cache = ReadFile(file_source, buffer, 32, 1);
+ WriteFile(file_destination, buffer, cache, 1);
+ }
+
+ CloseHandle(file_source);
+ CloseHandle(file_destination);
+
+ return true;
+}
+
+/*
+ * Recursively copies (the content) of a directory or file specified
+ * by "path" to "destination".
+ * Note that because of Sourcemod API limitations this currently does not
+ * takeover the file permissions (it leaves them default).
+ * Links will be resolved.
+ *
+ * @param path Source path
+ * @param destination Destination directory (This can only be a directory)
+ * @param stop_on_error Optional: Set to true to stop on error (ie can't read a file)
+ * @param dirMode Optional: File mode for directories that will be created (Default = 0755), don't forget to convert FROM octal
+ */
+stock bool:File_CopyRecursive(const String:path[], const String:destination[], bool:stop_on_error=false, dirMode=493)
+{
+ if (FileExists(path)) {
+ return File_Copy(path, destination);
+ }
+ else if (DirExists(path)) {
+ return Sub_File_CopyRecursive(path, destination, stop_on_error, FileType_Directory, dirMode);
+ }
+ else {
+ return false;
+ }
+}
+
+static stock bool:Sub_File_CopyRecursive(const String:path[], const String:destination[], bool:stop_on_error=false, FileType:fileType, dirMode)
+{
+ if (fileType == FileType_File) {
+ return File_Copy(path, destination);
+ }
+ else if (fileType == FileType_Directory) {
+
+ if (!CreateDirectory(destination, dirMode) && stop_on_error) {
+ return false;
+ }
+
+ new Handle:directory = OpenDirectory(path);
+
+ if (directory == INVALID_HANDLE) {
+ return false;
+ }
+
+ decl
+ String:source_buffer[PLATFORM_MAX_PATH],
+ String:destination_buffer[PLATFORM_MAX_PATH];
+ new FileType:type;
+
+ while (ReadDirEntry(directory, source_buffer, sizeof(source_buffer), type)) {
+
+ if (StrEqual(source_buffer, "..") || StrEqual(source_buffer, ".")) {
+ continue;
+ }
+
+ Format(destination_buffer, sizeof(destination_buffer), "%s/%s", destination, source_buffer);
+ Format(source_buffer, sizeof(source_buffer), "%s/%s", path, source_buffer);
+
+ if (type == FileType_File) {
+ File_Copy(source_buffer, destination_buffer);
+ }
+ else if (type == FileType_Directory) {
+
+ if (!File_CopyRecursive(source_buffer, destination_buffer, stop_on_error, dirMode) && stop_on_error) {
+ CloseHandle(directory);
+ return false;
+ }
+ }
+ }
+
+ CloseHandle(directory);
+ }
+ else if (fileType == FileType_Unknown) {
+ return false;
+ }
+
+ return true;
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/game.inc b/sourcemod-1.5-dev/scripting/include/smlib/game.inc
new file mode 100644
index 0000000..b468de9
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/game.inc
@@ -0,0 +1,58 @@
+#if defined _smlib_game_included
+ #endinput
+#endif
+#define _smlib_game_included
+
+#include <sourcemod>
+#include <sdktools_functions>
+#include <sdktools_entinput>
+
+/*
+ * End's the game and displays the scoreboard with intermission time.
+ *
+ * @noparam
+ * @return True on success, false otherwise
+ */
+stock bool:Game_End()
+{
+ new game_end = FindEntityByClassname(-1, "game_end");
+
+ if (game_end == -1) {
+ game_end = CreateEntityByName("game_end");
+
+ if (game_end == -1) {
+ ThrowError("Unable to find or create entity \"game_end\"");
+ }
+ }
+
+ return AcceptEntityInput(game_end, "EndGame");
+}
+
+/*
+ * End's the current round, allows specifying the winning
+ * team and more.
+ * This function currently works in TF2 only (it uses the game_round_win entity).
+ *
+ * @param team The winning Team, pass 0 for Sudden Death mode (no winning team)
+ * @param forceMapReset If to force the map to reset during the force respawn after the round is over.
+ * @param switchTeams If to switch the teams when the game is going to be reset.
+ * @return True on success, false otherwise
+ */
+stock bool:Game_EndRound(team=0, bool:forceMapReset=false, bool:switchTeams=false)
+{
+ new game_round_win = FindEntityByClassname(-1, "game_round_win");
+
+ if (game_round_win == -1) {
+ game_round_win = CreateEntityByName("game_end");
+
+ if (game_round_win == -1) {
+ ThrowError("Unable to find or create entity \"game_round_win\"");
+ }
+ }
+
+ DispatchKeyValue(game_round_win, "TeamNum" , (team ? "true" : "false"));
+ DispatchKeyValue(game_round_win, "force_map_reset" , (forceMapReset? "true" : "false"));
+ DispatchKeyValue(game_round_win, "switch_teams" , (switchTeams ? "true" : "false"));
+
+ return AcceptEntityInput(game_round_win, "RoundWin");
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/general.inc b/sourcemod-1.5-dev/scripting/include/smlib/general.inc
new file mode 100644
index 0000000..a7d004c
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/general.inc
@@ -0,0 +1,251 @@
+#if defined _smlib_general_included
+ #endinput
+#endif
+#define _smlib_general_included
+
+#include <sourcemod>
+#include <sdktools_stringtables>
+#include <smlib/math>
+
+#define TIME_TO_TICKS(%1) ( (int)( 0.5 + (float)(%1) / GetTickInterval() ) )
+#define TICKS_TO_TIME(%1) ( GetTickInterval() * %1 )
+#define ROUND_TO_TICKS(%1) ( TICK_INTERVAL * TIME_TO_TICKS( %1 ) )
+
+/*
+ * Precaches the given model.
+ * It's best to call this OnMapStart().
+ *
+ * @param material Path of the material to precache.
+ * @return Returns the material index, INVALID_STRING_INDEX on error.
+ */
+stock PrecacheMaterial(const String:material[])
+{
+ static materialNames = INVALID_STRING_TABLE;
+
+ if (materialNames == INVALID_STRING_TABLE) {
+ if ((materialNames = FindStringTable("Materials")) == INVALID_STRING_TABLE) {
+ return INVALID_STRING_INDEX;
+ }
+ }
+
+ new index = FindStringIndex2(materialNames, material);
+ if (index == INVALID_STRING_INDEX) {
+ new numStrings = GetStringTableNumStrings(materialNames);
+ if (numStrings >= GetStringTableMaxStrings(materialNames)) {
+ return INVALID_STRING_INDEX;
+ }
+
+ AddToStringTable(materialNames, material);
+ index = numStrings;
+ }
+
+ return index;
+}
+
+/*
+ * Checks if the material is precached.
+ *
+ * @param material Path of the material.
+ * @return True if it is precached, false otherwise.
+ */
+stock bool:IsMaterialPrecached(const String:material[])
+{
+ static materialNames = INVALID_STRING_TABLE;
+
+ if (materialNames == INVALID_STRING_TABLE) {
+ if ((materialNames = FindStringTable("Materials")) == INVALID_STRING_TABLE) {
+ return false;
+ }
+ }
+
+ return (FindStringIndex2(materialNames, material) != INVALID_STRING_INDEX);
+}
+
+/*
+ * Precaches the given particle system.
+ * It's best to call this OnMapStart().
+ * Code based on Rochellecrab's, thanks.
+ *
+ * @param particleSystem Name of the particle system to precache.
+ * @return Returns the particle system index, INVALID_STRING_INDEX on error.
+ */
+stock PrecacheParticleSystem(const String:particleSystem[])
+{
+ static particleEffectNames = INVALID_STRING_TABLE;
+
+ if (particleEffectNames == INVALID_STRING_TABLE) {
+ if ((particleEffectNames = FindStringTable("ParticleEffectNames")) == INVALID_STRING_TABLE) {
+ return INVALID_STRING_INDEX;
+ }
+ }
+
+ new index = FindStringIndex2(particleEffectNames, particleSystem);
+ if (index == INVALID_STRING_INDEX) {
+ new numStrings = GetStringTableNumStrings(particleEffectNames);
+ if (numStrings >= GetStringTableMaxStrings(particleEffectNames)) {
+ return INVALID_STRING_INDEX;
+ }
+
+ AddToStringTable(particleEffectNames, particleSystem);
+ index = numStrings;
+ }
+
+ return index;
+}
+
+/*
+ * Checks if the particle system is precached.
+ *
+ * @param material Name of the particle system
+ * @return True if it is precached, false otherwise.
+ */
+stock bool:IsParticleSystemPrecached(const String:particleSystem[])
+{
+ static particleEffectNames = INVALID_STRING_TABLE;
+
+ if (particleEffectNames == INVALID_STRING_TABLE) {
+ if ((particleEffectNames = FindStringTable("ParticleEffectNames")) == INVALID_STRING_TABLE) {
+ return false;
+ }
+ }
+
+ return (FindStringIndex2(particleEffectNames, particleSystem) != INVALID_STRING_INDEX);
+}
+
+/*
+ * Searches for the index of a given string in a string table.
+ *
+ * @param table String table name.
+ * @param str String to find.
+ * @return String index if found, INVALID_STRING_INDEX otherwise.
+ */
+stock FindStringIndexByTableName(const String:table[], const String:str[])
+{
+ new tableIndex = INVALID_STRING_TABLE;
+ if ((tableIndex = FindStringTable("ParticleEffectNames")) == INVALID_STRING_TABLE) {
+ return INVALID_STRING_INDEX;
+ }
+
+ return FindStringIndex2(tableIndex, str);
+}
+
+/*
+ * Rewrite of FindStringIndex, because in my tests
+ * FindStringIndex failed to work correctly.
+ * Searches for the index of a given string in a string table.
+ *
+ * @param tableidx A string table index.
+ * @param str String to find.
+ * @return String index if found, INVALID_STRING_INDEX otherwise.
+ */
+stock FindStringIndex2(tableidx, const String:str[])
+{
+ decl String:buf[1024];
+
+ new numStrings = GetStringTableNumStrings(tableidx);
+ for (new i=0; i < numStrings; i++) {
+ ReadStringTable(tableidx, i, buf, sizeof(buf));
+
+ if (StrEqual(buf, str)) {
+ return i;
+ }
+ }
+
+ return INVALID_STRING_INDEX;
+}
+
+/*
+ * Converts a long IP to a dotted format String.
+ *
+ * @param ip IP Long
+ * @param buffer String Buffer (size = 16)
+ * @param size String Buffer size
+ * @noreturn
+ */
+stock LongToIP(ip, String:buffer[], size)
+{
+ Format(
+ buffer, size,
+ "%d.%d.%d.%d",
+ (ip >> 24) & 0xFF,
+ (ip >> 16) & 0xFF,
+ (ip >> 8 ) & 0xFF,
+ ip & 0xFF
+ );
+}
+
+/*
+ * Converts a dotted format String IP to a long.
+ *
+ * @param ip IP String
+ * @return Long IP
+ */
+stock IPToLong(const String:ip[])
+{
+ decl String:pieces[4][4];
+
+ if (ExplodeString(ip, ".", pieces, sizeof(pieces), sizeof(pieces[])) != 4) {
+ return 0;
+ }
+
+ return (
+ StringToInt(pieces[0]) << 24 |
+ StringToInt(pieces[1]) << 16 |
+ StringToInt(pieces[2]) << 8 |
+ StringToInt(pieces[3])
+ );
+}
+
+static localIPRanges[] =
+{
+ 10 << 24, // 10.
+ 127 << 24 | 1 , // 127.0.0.1
+ 127 << 24 | 16 << 16, // 127.16.
+ 192 << 24 | 168 << 16, // 192.168.
+};
+
+/*
+ * Checks whether an IP is a private/internal IP
+ *
+ * @param ip IP Long
+ * @return True if the IP is local, false otherwise.
+ */
+stock bool:IsIPLocal(ip)
+{
+ new range, bits, move, bool:matches;
+
+ for (new i=0; i < sizeof(localIPRanges); i++) {
+
+ range = localIPRanges[i];
+ matches = true;
+
+ for (new j=0; j < 4; j++) {
+ move = j * 8;
+ bits = (range >> move) & 0xFF;
+
+ if (bits && bits != ((ip >> move) & 0xFF)) {
+ matches = false;
+ }
+ }
+
+ if (matches) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * Closes the given hindle and sets it to INVALID_HANDLE.
+ *
+ * @param handle handle
+ * @noreturn
+ */
+stock ClearHandle(&Handle:handle)
+{
+ if (handle != INVALID_HANDLE) {
+ CloseHandle(handle);
+ handle = INVALID_HANDLE;
+ }
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/math.inc b/sourcemod-1.5-dev/scripting/include/smlib/math.inc
new file mode 100644
index 0000000..faefb82
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/math.inc
@@ -0,0 +1,344 @@
+#if defined _smlib_math_included
+ #endinput
+#endif
+#define _smlib_math_included
+
+#include <sourcemod>
+
+#define SIZE_OF_INT 2147483647 // without 0
+#define INT_MAX_DIGITS 10
+
+#define GAMEUNITS_TO_METERS 0.01905
+#define METERS_TO_GAMEUNITS 52.49343832020997
+#define METERS_TO_FEET 3.2808399
+#define FEET_TO_METERS 0.3048
+#define KILOMETERS_TO_MILES 0.62137
+
+enum VecAngle
+{
+ ANG_ALPHA,
+ ANG_BETA,
+ ANG_GAMMA
+}
+
+/**
+ * Makes a negative integer number to a positive integer number.
+ * This is faster than Sourcemod's native FloatAbs() for integers.
+ * Use FloatAbs() for Float numbers.
+ *
+ * @param number A number that can be positive or negative.
+ * @return Positive number.
+ */
+stock Math_Abs(value)
+{
+ return (value ^ (value >> 31)) - (value >> 31);
+}
+
+/**
+ * Checks if 2 vectors are equal.
+ * You can specfiy a tolerance, which is the maximum distance at which vectors are considered equals
+ *
+ * @param vec1 First vector (3 dim array)
+ * @param vec2 Second vector (3 dim array)
+ * @param tolerance If you want to check that those vectors are somewhat even. 0.0 means they are 100% even if this function returns true.
+ * @return True if vectors are equal, false otherwise.
+ */
+stock bool:Math_VectorsEqual(Float:vec1[3], Float:vec2[3], Float:tolerance=0.0)
+{
+ new Float:distance = GetVectorDistance(vec1, vec2, true);
+
+ return distance <= (tolerance * tolerance);
+}
+
+/**
+ * Sets the given value to min
+ * if the value is smaller than the given.
+ *
+ * @param value Value
+ * @param min Min Value used as lower border
+ * @return Correct value not lower than min
+ */
+stock any:Math_Min(any:value, any:min)
+{
+ if (value < min) {
+ value = min;
+ }
+
+ return value;
+}
+
+/**
+ * Sets the given value to max
+ * if the value is greater than the given.
+ *
+ * @param value Value
+ * @param max Max Value used as upper border
+ * @return Correct value not upper than max
+ */
+stock any:Math_Max(any:value, any:max)
+{
+ if (value > max) {
+ value = max;
+ }
+
+ return value;
+}
+
+/**
+ * Makes sure a value is within a certain range and
+ * returns the value.
+ * If the value is outside the range it is set to either
+ * min or max, if it is inside the range it will just return
+ * the specified value.
+ *
+ * @param value Value
+ * @param min Min value used as lower border
+ * @param max Max value used as upper border
+ * @return Correct value not lower than min and not greater than max.
+ */
+stock any:Math_Clamp(any:value, any:min, any:max)
+{
+ value = Math_Min(value, min);
+ value = Math_Max(value, max);
+
+ return value;
+}
+
+/*
+ * Checks if the value is within the given bounds (min & max).
+ *
+ * @param value The value you want to check.
+ * @param min The lower border.
+ * @param max The upper border.
+ * @return True if the value is within bounds (bigger or equal min / smaller or equal max), false otherwise.
+ */
+stock bool:Math_IsInBounds(any:value, any:min, any:max)
+{
+ if (value < min || value > max) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Let's the specified value "overflow" if it is outside the given limit.
+ * This is like with integers when it reaches a value above the max possible
+ * integer size.
+ *
+ * @param value Value
+ * @param min Min value used as lower border
+ * @param max Max value used as upper border
+ * @return Overflowed number
+ */
+stock any:Math_Overflow(any:value, any:min, any:max)
+{
+ return (value % max) + min;
+}
+
+/**
+ * Returns a random, uniform Integer number in the specified (inclusive) range.
+ * This is safe to use multiple times in a function.
+ * The seed is set automatically for each plugin.
+ * Rewritten by MatthiasVance, thanks.
+ *
+ * @param min Min value used as lower border
+ * @param max Max value used as upper border
+ * @return Random Integer number between min and max
+ */
+stock Math_GetRandomInt(min, max)
+{
+ new random = GetURandomInt();
+
+ if (random == 0) {
+ random++;
+ }
+
+ return RoundToCeil(float(random) / (float(SIZE_OF_INT) / float(max - min + 1))) + min - 1;
+}
+
+/**
+ * Returns a random, uniform Float number in the specified (inclusive) range.
+ * This is safe to use multiple times in a function.
+ * The seed is set automatically for each plugin.
+ *
+ * @param min Min value used as lower border
+ * @param max Max value used as upper border
+ * @return Random Float number between min and max
+ */
+stock Float:Math_GetRandomFloat(Float:min, Float:max)
+{
+ return (GetURandomFloat() * (max - min)) + min;
+}
+
+/**
+ * Gets the percentage of amount in all as Integer where
+ * amount and all are numbers and amount usually
+ * is a subset of all.
+ *
+ * @param value Integer value
+ * @param all Integer value
+ * @return An Integer value between 0 and 100 (inclusive).
+ */
+stock Math_GetPercentage(value, all) {
+ return RoundToNearest((float(value) / float(all)) * 100.0);
+}
+
+/**
+ * Gets the percentage of amount in all as Float where
+ * amount and all are numbers and amount usually
+ * is a subset of all.
+ *
+ * @param value Float value
+ * @param all Float value
+ * @return A Float value between 0.0 and 100.0 (inclusive).
+ */
+stock Float:Math_GetPercentageFloat(Float:value, Float:all) {
+ return (value / all) * 100.0;
+}
+
+/*
+ * Moves the start vector on a direct line to the end vector by the given scale.
+ * Note: If scale is 0.0 the output will be the same as the start vector and if scale is 1.0 the output vector will be the same as the end vector.
+ * Exmaple usage: Move an entity to another entity but only 12 units: Vector_MoveVector(entity1Origin,entity2Origin,(12.0 / GetVectorDistance(entity1Origin,entity2Origin)),newEntity1Origin); now only teleport your entity to newEntity1Origin.
+ *
+ * @param start The start vector where the imagined line starts.
+ * @param end The end vector where the imagined line ends.
+ * @param scale The position on the line 0.0 is the start 1.0 is the end.
+ * @param output Output vector
+ * @noreturn
+ */
+stock Math_MoveVector(const Float:start[3], const Float:end[3], Float:scale, Float:output[3])
+{
+ SubtractVectors(end,start,output);
+ ScaleVector(output,scale);
+ AddVectors(start,output,output);
+}
+
+/**
+ * Puts x, y and z into a vector.
+ *
+ * @param x Float value.
+ * @param y Float value.
+ * @param z Float value.
+ * @param result Output vector.
+ * @noreturn
+ */
+stock Math_MakeVector(const Float:x, const Float:y, const Float:z, Float:result[3])
+{
+ result[0] = x;
+ result[1] = y;
+ result[2] = z;
+}
+
+/**
+ * Rotates a vector around its zero-point.
+ * Note: As example you can rotate mins and maxs of an entity and then add its origin to mins and maxs to get its bounding box in relation to the world and its rotation.
+ * When used with players use the following angle input:
+ * angles[0] = 0.0;
+ * angles[1] = 0.0;
+ * angles[2] = playerEyeAngles[1];
+ *
+ * @param vec Vector to rotate.
+ * @param angles How to rotate the vector.
+ * @param result Output vector.
+ * @noreturn
+ */
+stock Math_RotateVector(const Float:vec[3], const Float:angles[3], Float:result[3])
+{
+ // First the angle/radiant calculations
+ decl Float:rad[3];
+ // I don't really know why, but the alpha, beta, gamma order of the angles are messed up...
+ // 2 = xAxis
+ // 0 = yAxis
+ // 1 = zAxis
+ rad[0] = DegToRad(angles[2]);
+ rad[1] = DegToRad(angles[0]);
+ rad[2] = DegToRad(angles[1]);
+
+ // Pre-calc function calls
+ new Float:cosAlpha = Cosine(rad[0]);
+ new Float:sinAlpha = Sine(rad[0]);
+ new Float:cosBeta = Cosine(rad[1]);
+ new Float:sinBeta = Sine(rad[1]);
+ new Float:cosGamma = Cosine(rad[2]);
+ new Float:sinGamma = Sine(rad[2]);
+
+ // 3D rotation matrix for more information: http://en.wikipedia.org/wiki/Rotation_matrix#In_three_dimensions
+ new Float:x = vec[0], Float:y = vec[1], Float:z = vec[2];
+ new Float:newX, Float:newY, Float:newZ;
+ newY = cosAlpha*y - sinAlpha*z;
+ newZ = cosAlpha*z + sinAlpha*y;
+ y = newY;
+ z = newZ;
+
+ newX = cosBeta*x + sinBeta*z;
+ newZ = cosBeta*z - sinBeta*x;
+ x = newX;
+ z = newZ;
+
+ newX = cosGamma*x - sinGamma*y;
+ newY = cosGamma*y + sinGamma*x;
+ x = newX;
+ y = newY;
+
+ // Store everything...
+ result[0] = x;
+ result[1] = y;
+ result[2] = z;
+}
+
+/**
+ * Converts Source Game Units to metric Meters
+ *
+ * @param units Float value
+ * @return Meters as Float value.
+ */
+stock Float:Math_UnitsToMeters(Float:units)
+{
+ return (units * GAMEUNITS_TO_METERS);
+}
+
+/**
+ * Converts Source Game Units to Meters
+ *
+ * @param units Float value
+ * @return Feet as Float value.
+ */
+stock Float:Math_UnitsToFeet(Float:units)
+{
+ return (Math_UnitsToMeters(units) * METERS_TO_FEET);
+}
+
+/**
+ * Converts Source Game Units to Centimeters
+ *
+ * @param units Float value
+ * @return Centimeters as Float value.
+ */
+stock Float:Math_UnitsToCentimeters(Float:units)
+{
+ return (Math_UnitsToMeters(units) * 100.0);
+}
+
+/**
+ * Converts Source Game Units to Kilometers
+ *
+ * @param units Float value
+ * @return Kilometers as Float value.
+ */
+stock Float:Math_UnitsToKilometers(Float:units)
+{
+ return (Math_UnitsToMeters(units) / 1000.0);
+}
+
+/**
+ * Converts Source Game Units to Miles
+ *
+ * @param units Float value
+ * @return Miles as Float value.
+ */
+stock Float:Math_UnitsToMiles(Float:units)
+{
+ return (Math_UnitsToKilometers(units) * KILOMETERS_TO_MILES);
+} \ No newline at end of file
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/menus.inc b/sourcemod-1.5-dev/scripting/include/smlib/menus.inc
new file mode 100644
index 0000000..c0c825d
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/menus.inc
@@ -0,0 +1,38 @@
+#if defined _smlib_menus_included
+ #endinput
+#endif
+#define _smlib_menus_included
+
+#include <sourcemod>
+#include <smlib/math>
+
+/**
+ * Adds an option to a menu with a String display but an integer
+ * identifying the option.
+ *
+ * @param menu Handle to the menu
+ * @param value Integer value for the option
+ * @param display Display text for the menu
+ * @noreturn
+ */
+stock Menu_AddIntItem(Handle:menu, any:value, String:display[])
+{
+ decl String:buffer[INT_MAX_DIGITS + 1];
+ IntToString(value, buffer, sizeof(buffer));
+ AddMenuItem(menu, buffer, display);
+}
+
+/**
+ * Retrieves an integer-value choice from a menu, where the
+ * menu's information strings were created as integers.
+ *
+ * @param menu Handle to the menu
+ * @param param2 The item position selected from the menu.
+ * @return Integer choice from the menu, or 0 if the integer could not be parsed.
+ */
+stock any:Menu_GetIntItem(Handle:menu, any:param2)
+{
+ decl String:buffer[INT_MAX_DIGITS + 1];
+ GetMenuItem(menu, param2, buffer, sizeof(buffer));
+ return StringToInt(buffer);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/server.inc b/sourcemod-1.5-dev/scripting/include/smlib/server.inc
new file mode 100644
index 0000000..5ae1837
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/server.inc
@@ -0,0 +1,135 @@
+#if defined _smlib_server_included
+ #endinput
+#endif
+#define _smlib_server_included
+
+#include <sourcemod>
+#include <smlib/general>
+
+/*
+ * Gets the server's public/external (default) or
+ * private/local (usually server's behind a NAT) IP.
+ * If your server is behind a NAT Router, you need the SteamTools
+ * extension available at http://forums.alliedmods.net/showthread.php?t=129763
+ * to get the public IP. <steamtools> has to be included BEFORE <smlib>.
+ * If the server is not behind NAT, the public IP is the same as the private IP.
+ *
+ * @param public Set to true to retrieve the server's public/external IP, false otherwise.
+ * @return Long IP or 0 if the IP couldn't be retrieved.
+ */
+stock Server_GetIP(bool:public_=true)
+{
+ new ip = 0;
+
+ static Handle:cvHostip = INVALID_HANDLE;
+
+ if (cvHostip == INVALID_HANDLE) {
+ cvHostip = FindConVar("hostip");
+ MarkNativeAsOptional("Steam_GetPublicIP");
+ }
+
+ if (cvHostip != INVALID_HANDLE) {
+ ip = GetConVarInt(cvHostip);
+ }
+
+ if (ip != 0 && IsIPLocal(ip) == public_) {
+ ip = 0;
+ }
+
+#if defined _steamtools_included
+ if (ip == 0) {
+ if (CanTestFeatures() && GetFeatureStatus(FeatureType_Native, "Steam_GetPublicIP") == FeatureStatus_Available) {
+ decl octets[4];
+ Steam_GetPublicIP(octets);
+
+ ip =
+ octets[0] << 24 |
+ octets[1] << 16 |
+ octets[2] << 8 |
+ octets[3];
+
+ if (IsIPLocal(ip) == public_) {
+ ip = 0;
+ }
+ }
+ }
+#endif
+
+ return ip;
+}
+
+/*
+ * Gets the server's public/external (default) or
+ * private/local (usually server's behind a NAT) as IP String in dotted format.
+ * If your server is behind a NAT Router, you need the SteamTools
+ * extension available at http://forums.alliedmods.net/showthread.php?t=129763
+ * to get the public IP. <steamtools> has to be included BEFORE <smlib>.
+ * If the public IP couldn't be found, an empty String is returned.
+ * If the server is not behind NAT, the public IP is the same as the private IP.
+ *
+ * @param buffer String buffer (size=16)
+ * @param size String buffer size.
+ * @param public Set to true to retrieve the server's public/external IP, false otherwise.
+ * @return True on success, false otherwise.
+ */
+stock bool:Server_GetIPString(String:buffer[], size, bool:public_=true)
+{
+ new ip;
+
+ if ((ip = Server_GetIP(public_)) == 0) {
+ buffer[0] = '\0';
+ return false;
+ }
+
+ LongToIP(ip, buffer, size);
+
+ return true;
+}
+
+/*
+ * Gets the server's local port.
+ *
+ * @noparam
+ * @return The server's port, 0 if there is no port.
+ */
+stock Server_GetPort()
+{
+ static Handle:cvHostport = INVALID_HANDLE;
+
+ if (cvHostport == INVALID_HANDLE) {
+ cvHostport = FindConVar("hostport");
+ }
+
+ if (cvHostport == INVALID_HANDLE) {
+ return 0;
+ }
+
+ new port = GetConVarInt(cvHostport);
+
+ return port;
+}
+
+/*
+ * Gets the server's hostname
+ *
+ * @param hostname String buffer
+ * @param size String buffer size
+ * @return True on success, false otherwise.
+ */
+stock bool:Server_GetHostName(String:buffer[], size)
+{
+ static Handle:cvHostname = INVALID_HANDLE;
+
+ if (cvHostname == INVALID_HANDLE) {
+ cvHostname = FindConVar("hostname");
+ }
+
+ if (cvHostname == INVALID_HANDLE) {
+ buffer[0] = '\0';
+ return false;
+ }
+
+ GetConVarString(cvHostname, buffer, size);
+
+ return true;
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/sql.inc b/sourcemod-1.5-dev/scripting/include/smlib/sql.inc
new file mode 100644
index 0000000..8bc8ca6
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/sql.inc
@@ -0,0 +1,108 @@
+#if defined _smlib_sql_included
+ #endinput
+#endif
+#define _smlib_sql_included
+
+#include <sourcemod>
+#include <dbi>
+
+/**
+ * Executes a threaded SQL Query (See: SQL_TQuery)
+ * This function supports the printf Syntax.
+ *
+ *
+ * @param database A database Handle.
+ * @param callback Callback; database is in "owner" and the query Handle is passed in "hndl".
+ * @param data Extra data value to pass to the callback.
+ * @param format Query string, printf syntax supported
+ * @param priority Priority queue to use
+ * @param ... Variable number of format parameters.
+ * @noreturn
+ */
+stock SQL_TQueryF(Handle:database, SQLTCallback:callback, any:data, DBPriority:priority=DBPrio_Normal, const String:format[], any:...) {
+
+ if (database == INVALID_HANDLE) {
+ ThrowError("[SMLIB] Error: Invalid database handle.");
+ return;
+ }
+
+ decl String:query[16384];
+ VFormat(query, sizeof(query), format, 6);
+
+ SQL_TQuery(database, callback, query, data, priority);
+}
+
+/**
+ * Fetches an integer from a field in the current row of a result set (See: SQL_FetchInt)
+ *
+ * @param query A query (or statement) Handle.
+ * @param field The field index (starting from 0).
+ * @param result Optional variable to store the status of the return value.
+ * @return An integer value.
+ * @error Invalid query Handle or field index, invalid
+ * type conversion requested from the database,
+ * or no current result set.
+ */
+stock SQL_FetchIntByName(Handle:query, String:fieldName[], &DBResult:result=DBVal_Error) {
+
+ new fieldNum;
+ SQL_FieldNameToNum(query, fieldName, fieldNum);
+
+ return SQL_FetchInt(query, fieldNum, result);
+}
+
+/**
+ * Fetches a bool from a field in the current row of a result set (See: SQL_FetchInt)
+ *
+ * @param query A query (or statement) Handle.
+ * @param field The field index (starting from 0).
+ * @param result Optional variable to store the status of the return value.
+ * @return A bool value.
+ * @error Invalid query Handle or field index, invalid
+ * type conversion requested from the database,
+ * or no current result set.
+ */
+stock bool:SQL_FetchBoolByName(Handle:query, String:fieldName[], &DBResult:result=DBVal_Error) {
+
+ return bool:SQL_FetchIntByName(query, fieldName, result);
+}
+
+/**
+ * Fetches a float from a field in the current row of a result set. (See: SQL_FetchFloat)
+ *
+ * @param query A query (or statement) Handle.
+ * @param field The field index (starting from 0).
+ * @param result Optional variable to store the status of the return value.
+ * @return A float value.
+ * @error Invalid query Handle or field index, invalid
+ * type conversion requested from the database,
+ * or no current result set.
+ */
+stock Float:SQL_FetchFloatByName(Handle:query, String:fieldName[], &DBResult:result=DBVal_Error) {
+
+ new fieldNum;
+ SQL_FieldNameToNum(query, fieldName, fieldNum);
+
+ return SQL_FetchFloat(query, fieldNum, result);
+}
+
+/**
+ * Fetches a string from a field in the current row of a result set. (See: SQL_FetchString)
+ *
+ * @param query A query (or statement) Handle.
+ * @param field The field index (starting from 0).
+ * @param buffer String buffer.
+ * @param maxlength Maximum size of the string buffer.
+ * @param result Optional variable to store the status of the return value.
+ * @return Number of bytes written.
+ * @error Invalid query Handle or field index, invalid
+ * type conversion requested from the database,
+ * or no current result set.
+ */
+stock SQL_FetchStringByName(Handle:query, String:fieldName[], String:buffer[], maxlength, &DBResult:result=DBVal_Error) {
+
+ new fieldNum;
+ SQL_FieldNameToNum(query, fieldName, fieldNum);
+
+ return SQL_FetchString(query, fieldNum, buffer, maxlength, result);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/strings.inc b/sourcemod-1.5-dev/scripting/include/smlib/strings.inc
new file mode 100644
index 0000000..e675db7
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/strings.inc
@@ -0,0 +1,229 @@
+#if defined _smlib_strings_included
+ #endinput
+#endif
+#define _smlib_strings_included
+
+#include <sourcemod>
+#include <smlib/math>
+
+/**
+ * Checks if the string is numeric.
+ * This correctly handles + - . in the String.
+ *
+ * @param str String to check.
+ * @return True if the String is numeric, false otherwise..
+ */
+stock bool:String_IsNumeric(const String:str[])
+{
+ new x=0;
+ new dotsFound=0;
+ new numbersFound=0;
+
+ if (str[x] == '+' || str[x] == '-') {
+ x++;
+ }
+
+ while (str[x] != '\0') {
+
+ if (IsCharNumeric(str[x])) {
+ numbersFound++;
+ }
+ else if (str[x] == '.') {
+ dotsFound++;
+
+ if (dotsFound > 1) {
+ return false;
+ }
+ }
+ else {
+ return false;
+ }
+
+ x++;
+ }
+
+ if (!numbersFound) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Trims a string by removing the specified chars from beginning and ending.
+ * Removes all ' ', '\t', '\r', '\n' characters by default.
+ * The Output String can be the same as the Input String.
+ *
+ * @param str Input String.
+ * @param output Output String (Can be the as the input).
+ * @param size Size of the output String.
+ * @param chars Characters to remove.
+ * @noreturn
+ */
+stock String_Trim(const String:str[], String:output[], size, const String:chrs[]=" \t\r\n")
+{
+ new x=0;
+ while (str[x] != '\0' && FindCharInString(chrs, str[x]) != -1) {
+ x++;
+ }
+
+ x = strcopy(output, size, str[x]);
+ x--;
+
+ while (x >= 0 && FindCharInString(chrs, output[x]) != -1) {
+ x--;
+ }
+
+ output[++x] = '\0';
+}
+
+/**
+ * Removes a list of strings from a string.
+ *
+ * @param buffer Input/Ourput buffer.
+ * @param removeList A list of strings which should be removed from buffer.
+ * @param size Number of Strings in the List.
+ * @param caseSensitive If true, comparison is case sensitive. If false (default), comparison is case insensitive.
+ * @noreturn
+ */
+stock String_RemoveList(String:buffer[], String:removeList[][], size, bool:caseSensitive=false)
+{
+ for (new i=0; i < size; i++) {
+ ReplaceString(buffer, SIZE_OF_INT, removeList[i], "", caseSensitive);
+ }
+}
+
+/**
+ * Converts the whole String to lower case.
+ * Only works with alphabetical characters (not ÖÄÜ) because Sourcemod suxx !
+ * The Output String can be the same as the Input String.
+ *
+ * @param input Input String.
+ * @param output Output String.
+ * @param size Max Size of the Output string
+ * @noreturn
+ */
+stock String_ToLower(const String:input[], String:output[], size)
+{
+ size--;
+
+ new x=0;
+ while (input[x] != '\0' && x < size) {
+
+ output[x] = CharToLower(input[x]);
+
+ x++;
+ }
+
+ output[x] = '\0';
+}
+
+/**
+ * Converts the whole String to upper case.
+ * Only works with alphabetical characters (not öäü) because Sourcemod suxx !
+ * The Output String can be the same as the Input String.
+ *
+ * @param input Input String.
+ * @param output Output String.
+ * @param size Max Size of the Output string
+ * @noreturn
+ */
+stock String_ToUpper(const String:input[], String:output[], size)
+{
+ size--;
+
+ new x=0;
+ while (input[x] != '\0' && x < size) {
+
+ output[x] = CharToUpper(input[x]);
+
+ x++;
+ }
+
+ output[x] = '\0';
+}
+
+/**
+ * Generates a random string.
+ *
+ *
+ * @param buffer String Buffer.
+ * @param size String Buffer size (must be length+1)
+ * @param length Number of characters being generated.
+ * @param chrs String for specifying the characters used for random character generation.
+ * By default it will use all letters of the alphabet (upper and lower) and all numbers.
+ * If you pass an empty String, it will use all readable ASCII characters (33 - 126)
+ * @noreturn
+ */
+stock String_GetRandom(String:buffer[], size, length=32, const String:chrs[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234556789")
+{
+ new random, len;
+ size--;
+
+ if (chrs[0] != '\0') {
+ len = strlen(chrs) - 1;
+ }
+
+ new n = 0;
+ while (n < length && n < size) {
+
+ if (chrs[0] == '\0') {
+ random = Math_GetRandomInt(33, 126);
+ buffer[n] = random;
+ }
+ else {
+ random = Math_GetRandomInt(0, len);
+ buffer[n] = chrs[random];
+ }
+
+ n++;
+ }
+
+ buffer[length] = '\0';
+}
+
+/**
+ * Checks if string str starts with subString.
+ *
+ *
+ * @param str String to check
+ * @param subString Sub-String to check in str
+ * @return True if str starts with subString, false otherwise.
+ */
+stock bool:String_StartsWith(const String:str[], const String:subString[])
+{
+ new n = 0;
+ while (str[n] != '\0' && subString[n] != '\0') {
+
+ if (str[n] != subString[n]) {
+ return false;
+ }
+
+ n++;
+ }
+
+ return true;
+}
+
+/**
+ * Checks if string str ends with subString.
+ *
+ *
+ * @param str String to check
+ * @param subString Sub-String to check in str
+ * @return True if str ends with subString, false otherwise.
+ */
+stock bool:String_EndsWith(const String:str[], const String:subString[])
+{
+ new n_str = strlen(str) - 1;
+ new n_subString = strlen(subString) - 1;
+
+ while (n_str != 0 && n_subString != 0) {
+
+ if (str[n_str--] != subString[n_subString--]) {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/teams.inc b/sourcemod-1.5-dev/scripting/include/smlib/teams.inc
new file mode 100644
index 0000000..bb6d725
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/teams.inc
@@ -0,0 +1,318 @@
+#if defined _smlib_teams_included
+ #endinput
+#endif
+#define _smlib_teams_included
+
+#include <sourcemod>
+#include <smlib/clients>
+#include <smlib/entities>
+
+#define MAX_TEAMS 32 // Max number of teams in a game
+#define MAX_TEAM_NAME_LENGTH 32 // Max length of a team's name
+
+// Team Defines
+#define TEAM_INVALID -1
+#define TEAM_UNASSIGNED 0
+#define TEAM_SPECTATOR 1
+#define TEAM_ONE 2
+#define TEAM_TWO 3
+#define TEAM_THREE 4
+#define TEAM_FOUR 5
+
+/*
+ * If one team is empty its assumed single team mode is enabled and the game won't start.
+ *
+ * @noparam
+ * @return True if one team is empty, false otherwise.
+ */
+stock bool:Team_HaveAllPlayers(bool:countFakeClients=true) {
+
+ new teamCount = GetTeamCount();
+ for (new i=2; i < teamCount; i++) {
+
+ if (Team_GetClientCount(i, ((countFakeClients) ? CLIENTFILTER_ALL : CLIENTFILTER_NOBOTS)) == 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*
+ * Returns the client count of the players in a team.
+ *
+ * @param team Team Index.
+ * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants).
+ * @return Client count in the server.
+ */
+stock Team_GetClientCount(team, flags=0)
+{
+ flags |= CLIENTFILTER_INGAME;
+
+ new numClients = 0;
+ for (new client=1; client <= MaxClients; client++) {
+
+ if (!Client_MatchesFilter(client, flags)) {
+ continue;
+ }
+
+ if (GetClientTeam(client) == team) {
+ numClients++;
+ }
+ }
+
+ return numClients;
+}
+
+/*
+ * Returns the client counts of the first two teams (eg.: Terrorists - Counter).
+ * Use this function for optimization if you have to get the counts of both teams,
+ * otherwise use Team_GetClientCount().
+ *
+ * @param team1 Pass an integer variable by reference
+ * @param team2 Pass an integer variable by reference
+ * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants).
+ * @noreturn
+ */
+stock Team_GetClientCounts(&team1=0, &team2=0, flags=0)
+{
+ flags |= CLIENTFILTER_INGAME;
+
+ for (new client=1; client <= MaxClients; client++) {
+
+ if (!Client_MatchesFilter(client, flags)) {
+ continue;
+ }
+
+ if (GetClientTeam(client) == TEAM_ONE) {
+ team1++;
+ }
+ else if (GetClientTeam(client) == TEAM_TWO) {
+ team2++;
+ }
+ }
+}
+
+/*
+ * Gets the name of a team.
+ * Don't call this before OnMapStart()
+ *
+ * @param index Team Index.
+ * @param str String buffer
+ * @param size String Buffer Size
+ * @return True on success, false otherwise
+ */
+stock bool:Team_GetName(index, String:str[], size)
+{
+ new edict = Team_GetEdict(index);
+
+ if (edict == -1) {
+ str[0] = '\0';
+ return false;
+ }
+
+ GetEntPropString(edict, Prop_Send, "m_szTeamname", str, size);
+
+ return true;
+}
+
+/*
+ * Changes a team's name.
+ * Use this carefully !
+ * Only set the teamname OnMapStart() or OnEntityCreated()
+ * when no players are ingame, otherwise it can crash the server.
+ *
+ * @param index Team Index.
+ * @param name New Name String
+ * @return True on success, false otherwise
+ */
+stock bool:Team_SetName(index, const String:name[])
+{
+ new edict = Team_GetEdict(index);
+
+ if (edict == -1) {
+ return false;
+ }
+
+ SetEntPropString(edict, Prop_Send, "m_szTeamname", name);
+ ChangeEdictState(edict, GetEntSendPropOffs(edict, "m_szTeamname", true));
+
+ return true;
+}
+
+/*
+ * Changes a team's score.
+ * Don't use this before OnMapStart().
+ *
+ * @param index Team Index.
+ * @return Team Score or -1 if the team is not valid.
+ */
+stock Team_GetScore(index)
+{
+ new edict = Team_GetEdict(index);
+
+ if (edict == -1) {
+ return -1;
+ }
+
+ return GetEntProp(edict, Prop_Send, "m_iScore");
+}
+
+/*
+ * Changes a team's score.
+ * Don't use this before OnMapStart().
+ *
+ * @param index Team Index.
+ * @param score Score value.
+ * @return True on success, false otherwise
+ */
+stock bool:Team_SetScore(index, score)
+{
+ new edict = Team_GetEdict(index);
+
+ if (edict == -1) {
+ return false;
+ }
+
+ SetEntProp(edict, Prop_Send, "m_iScore", score);
+
+ ChangeEdictState(edict, GetEntSendPropOffs(edict, "m_iScore", true));
+
+ return true;
+}
+
+/*
+ * Gets a team's edict (*team_manager) Team Index.
+ * Don't call this before OnMapStart()
+ *
+ * @param edict Edict
+ * @return Team Index
+ */
+stock Team_EdictGetNum(edict)
+{
+ return GetEntProp(edict, Prop_Send, "m_iTeamNum");
+}
+
+/*
+ * Check's whether the index is a valid team index or not.
+ * Don't call this before OnMapStart()
+ *
+ * @param index Index.
+ * @return True if the Index is a valid team, false otherwise.
+ */
+stock bool:Team_IsValid(index)
+{
+ return (Team_GetEdict(index) != -1);
+}
+
+/*
+ * Gets a team's edict (team_manager) Team Index.
+ * Don't call this before OnMapStart()
+ *
+ * @param index Edict
+ * @return Team Index
+ */
+stock Team_EdictIsValid(edict)
+{
+ return GetEntProp(edict, Prop_Send, "m_iTeamNum");
+}
+
+/*
+ * Gets a team's edict (team_manager).
+ * This function caches found team edicts.
+ * Don't call this before OnMapStart()
+ *
+ * @param index Team Index.
+ * @return Team edict or -1 if not found
+ */
+stock Team_GetEdict(index)
+{
+ static teams[MAX_TEAMS] = { INVALID_ENT_REFERENCE, ... };
+
+ if (index < 0 || index > MAX_TEAMS) {
+ return -1;
+ }
+
+ new edict = teams[index];
+ if (Entity_IsValid(edict)) {
+ return edict;
+ }
+
+ new bool:foundTeamManager = false;
+
+ new maxEntities = GetMaxEntities();
+ for (new entity=MaxClients+1; entity < maxEntities; entity++) {
+
+ if (!IsValidEntity(entity)) {
+ continue;
+ }
+
+ if (Entity_ClassNameMatches(entity, "team_manager", true)) {
+ foundTeamManager = true;
+ }
+ // Do not continue when no team managers are found anymore (for optimization)
+ else if (foundTeamManager) {
+ return -1;
+ }
+ else {
+ continue;
+ }
+
+ new num = Team_EdictGetNum(entity);
+
+ if (num >= 0 && num <= MAX_TEAMS) {
+ teams[num] = EntIndexToEntRef(entity);
+ }
+
+ if (num == index) {
+ return entity;
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * Trys to find a client in the specified team.
+ * This function is NOT random, it returns the first
+ * or the cached player (Use Client_GetRandom() instead).
+ *
+ * @param index Team Index.
+ * @return Client Index or -1 if no client was found in the specified team.
+ */
+stock Team_GetAnyClient(index)
+{
+ static client_cache[MAX_TEAMS] = -1;
+ new client;
+
+ if (index > 0) {
+ client = client_cache[index];
+
+ if (client > 0 && client <= MaxClients) {
+
+ if (IsClientInGame(client) && GetClientTeam(client) == index) {
+ return client;
+ }
+ }
+ else {
+ client = -1;
+ }
+ }
+
+ for (client=1; client <= MaxClients; client++) {
+
+ if (!IsClientInGame(client)) {
+ continue;
+ }
+
+ if (GetClientTeam(client) != index) {
+ continue;
+ }
+
+ client_cache[index] = client;
+
+ return client;
+ }
+
+ return -1;
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/vehicles.inc b/sourcemod-1.5-dev/scripting/include/smlib/vehicles.inc
new file mode 100644
index 0000000..fc4c917
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/vehicles.inc
@@ -0,0 +1,141 @@
+#if defined _smlib_vehicles_included
+ #endinput
+#endif
+#define _smlib_vehicles_included
+
+#include <sourcemod>
+#include <sdktools_entinput>
+#include <sdktools_functions>
+#include <smlib/entities>
+
+/**
+ * Returns the vehicle's driver.
+ * If there is no driver in the vehicle, -1 is returned.
+ *
+ * @param vehicle Entity index.
+ * @return Client index, or -1 if there is no driver.
+ */
+stock Vehicle_GetDriver(vehicle)
+{
+ new m_hVehicle = GetEntPropEnt(vehicle, Prop_Send, "m_hPlayer");
+
+ return m_hVehicle;
+}
+
+/**
+ * Returns whether there is a driver in the vehicle or not.
+ *
+ * @param vehicle Entity index.
+ * @return True if the vehicle has a driver, false otherwise
+ */
+stock bool:Vehicle_HasDriver(vehicle)
+{
+ return !(Vehicle_GetDriver(vehicle) == -1);
+}
+
+/**
+ * Kicks the driver ouf of the vehicle
+ *
+ * @param vehicle Entity index.
+ * @return True on success, false otherwise.
+ */
+stock bool:Vehicle_ExitDriver(vehicle)
+{
+ if (!Vehicle_HasDriver(vehicle)) {
+ return false;
+ }
+
+ return AcceptEntityInput(vehicle, "ExitVehicle");
+}
+
+/**
+ * Start's the vehicle's engine
+ *
+ * @param vehicle Entity index.
+ * @return True on success, false otherwise.
+ */
+stock bool:Vehicle_TurnOn(vehicle)
+{
+
+ return AcceptEntityInput(vehicle, "TurnOn");
+}
+
+/**
+ * Shuts down the vehicle's engine
+ *
+ * @param vehicle Entity index.
+ * @return True on success, false otherwise.
+ */
+stock bool:Vehicle_TurnOff(vehicle)
+{
+
+ return AcceptEntityInput(vehicle, "TurnOff");
+}
+
+/**
+ * Locks the vehicle.
+ *
+ * @param vehicle Entity index.
+ * @return True on success, false otherwise.
+ */
+stock bool:Vehicle_Lock(vehicle)
+{
+
+ return AcceptEntityInput(vehicle, "Lock");
+}
+
+/**
+ * Unlocks the vehicle.
+ *
+ * @param vehicle Entity index.
+ * @return True on success, false otherwise.
+ */
+stock bool:Vehicle_Unlock(vehicle)
+{
+
+ return AcceptEntityInput(vehicle, "Unlock");
+}
+
+/**
+ * Returns wether the entity is a valid vehicle or not.
+ *
+ * @param vehicle Entity index.
+ * @return True if it is a valid vehicle, false otherwise.
+ */
+stock bool:Vehicle_IsValid(vehicle)
+{
+ if (!Entity_IsValid(vehicle)) {
+ return false;
+ }
+
+ return Entity_ClassNameMatches(vehicle, "prop_vehicle", true);
+}
+
+/**
+ * Reads the vehicle script from a vehicle.
+ * This script contains all the vehicle settings like its speed
+ * and that stuff.
+ *
+ * @param vehicle Entity index.
+ * @param buffer String Buffer.
+ * @param size String Buffer size.
+ * @noreturn
+ */
+stock bool:Vehicle_GetScript(vehicle, String:buffer[], size)
+{
+ GetEntPropString(vehicle, Prop_Data, "m_vehicleScript", buffer, size);
+}
+
+/**
+ * Sets the script of a vehicle.
+ * This script contains all the vehicle settings like its speed
+ * and that stuff.
+ *
+ * @param vehicle Entity index.
+ * @param buffer Vehicle Script path.
+ * @noreturn
+ */
+stock bool:Vehicle_SetScript(vehicle, String:script[])
+{
+ DispatchKeyValue(vehicle, "vehiclescript", script);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/weapons.inc b/sourcemod-1.5-dev/scripting/include/smlib/weapons.inc
new file mode 100644
index 0000000..cc4bd18
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/weapons.inc
@@ -0,0 +1,399 @@
+#if defined _smlib_weapons_included
+ #endinput
+#endif
+#define _smlib_weapons_included
+
+#include <sourcemod>
+#include <sdktools_functions>
+#include <smlib/entities>
+
+#define MAX_WEAPON_OFFSET 64
+#define MAX_WEAPON_SLOTS 6 // hud item selection slots
+#define MAX_WEAPON_POSITIONS 20 // max number of items within a slot
+#define MAX_WEAPONS 48 // Max number of weapons availabl
+#define WEAPON_NOCLIP -1 // clip sizes set to this tell the weapon it doesn't use a clip
+#define MAX_AMMO_TYPES 32
+#define MAX_AMMO_SLOTS 32 // not really slots
+
+#define MAX_WEAPON_STRING 80
+#define MAX_WEAPON_PREFIX 16
+#define MAX_WEAPON_AMMO_NAME 32
+
+/*
+ * Gets the owner (usually a client) of the weapon
+ *
+ * @param weapon Weapon Entity.
+ * @return Owner of the weapon or INVALID_ENT_REFERENCE if the weapon has no owner.
+ */
+stock Weapon_GetOwner(weapon)
+{
+ return GetEntPropEnt(weapon, Prop_Data, "m_hOwner");
+}
+
+/*
+ * Sets the owner (usually a client) of the weapon
+ *
+ * @param weapon Weapon Entity.
+ * @param entity Entity Index.
+ * @noreturn
+ */
+stock Weapon_SetOwner(weapon, entity)
+{
+ SetEntPropEnt(weapon, Prop_Data, "m_hOwner", entity);
+}
+
+/*
+ * Checks whether the entity is a valid weapon or not.
+ *
+ * @param weapon Weapon Entity.
+ * @return True if the entity is a valid weapon, false otherwise.
+ */
+stock Weapon_IsValid(weapon)
+{
+ if (!IsValidEdict(weapon)) {
+ return false;
+ }
+
+ return Entity_ClassNameMatches(weapon, "weapon_", true);
+}
+
+/*
+ * Create's a weapon and spawns it in the world at the specified location.
+ *
+ * @param className Classname String of the weapon to spawn
+ * @param absOrigin Absolute Origin Vector where to spawn the weapon.
+ * @param absAngles Absolute Angles Vector.
+ * @return Weapon Index of the created weapon or INVALID_ENT_REFERENCE on error.
+ */
+stock Weapon_Create(const String:className[], Float:absOrigin[3], Float:absAngles[3])
+{
+ new weapon = Entity_Create(className);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ return INVALID_ENT_REFERENCE;
+ }
+
+ Entity_SetAbsOrigin(weapon, absOrigin);
+ Entity_SetAbsAngles(weapon, absAngles);
+
+ DispatchSpawn(weapon);
+
+ return weapon;
+}
+
+/*
+ * Create's a weapon and spawns it in the world at the specified location.
+ *
+ * @param className Classname String of the weapon to spawn
+ * @param absOrigin Absolute Origin Vector where to spawn the weapon.
+ * @param absAngles Absolute Angles Vector.
+ * @return Weapon Index of the created weapon or INVALID_ENT_REFERENCE on error.
+ */
+stock Weapon_CreateForOwner(client, const String:className[])
+{
+ decl Float:absOrigin[3], Float:absAngles[3];
+ Entity_GetAbsOrigin(client, absOrigin);
+ Entity_GetAbsAngles(client, absAngles);
+
+ new weapon = Weapon_Create(className, absOrigin, absAngles);
+
+ if (weapon == INVALID_ENT_REFERENCE) {
+ return INVALID_ENT_REFERENCE;
+ }
+
+ Entity_SetOwner(weapon, client);
+
+ return weapon;
+}
+
+/*
+ * Gets the weapon's subtype.
+ * The subtype is only used when a player has multiple weapons of the same type.
+ *
+ * @param weapon Weapon Entity.
+ * @return Subtype of the weapon.
+ */
+stock Weapon_GetSubType(weapon)
+{
+ return GetEntProp(weapon, Prop_Data, "m_iSubType");
+}
+
+/*
+ * Is the weapon currently reloading ?
+ *
+ * @param weapon Weapon Entity.
+ * @return True if weapon is currently reloading, false if not.
+ */
+stock bool:Weapon_IsReloading(weapon)
+{
+ return bool:GetEntProp(weapon, Prop_Data, "m_bInReload");
+}
+
+/*
+ * Weapon m_iState
+ */
+#define WEAPON_IS_ONTARGET 0x40
+#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
+
+/*
+ * Get's the state of the weapon.
+ * This returns whether the weapon is currently carried by a client,
+ * if it is active and if it is on a target.
+ *
+ * @param weapon Weapon Entity.
+ * @return Weapon State.
+ */
+stock Weapon_GetState(weapon)
+{
+ return GetEntProp(weapon, Prop_Data, "m_iState");
+}
+
+/*
+ * Returns whether the weapon can fire primary ammo under water.
+ *
+ * @param weapon Weapon Entity.
+ * @return True or False.
+ */
+stock bool:Weapon_FiresUnderWater(weapon)
+{
+ return bool:GetEntProp(weapon, Prop_Data, "m_bFiresUnderwater");
+}
+
+/*
+ * Sets if the weapon can fire primary ammo under water.
+ *
+ * @param weapon Weapon Entity.
+ * @param can True or False.
+ * @noreturn
+ */
+stock Weapon_SetFiresUnderWater(weapon, bool:can=true)
+{
+ SetEntProp(weapon, Prop_Data, "m_bFiresUnderwater", _:can);
+}
+
+/*
+ * Returns whether the weapon can fire secondary ammo under water.
+ *
+ * @param weapon Weapon Entity.
+ * @return True or False.
+ */
+stock bool:Weapon_FiresUnderWaterAlt(weapon)
+{
+ return bool:GetEntProp(weapon, Prop_Data, "m_bAltFiresUnderwater");
+}
+
+/*
+ * Sets if the weapon can fire secondary ammo under water.
+ *
+ * @param weapon Weapon Entity.
+ * @param can True or False.
+ * @noreturn
+ */
+stock Weapon_SetFiresUnderWaterAlt(weapon, bool:can=true)
+{
+ SetEntProp(weapon, Prop_Data, "m_bAltFiresUnderwater", _:can);
+}
+
+/*
+ * Gets the primary ammo Type (int offset)
+ *
+ * @param weapon Weapon Entity.
+ * @return Primary ammo type value.
+ */
+stock Weapon_GetPrimaryAmmoType(weapon)
+{
+ return GetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoType");
+}
+
+/*
+ * Sets the primary ammo Type (int offset)
+ *
+ * @param weapon Weapon Entity.
+ * @param type Primary ammo type value.
+ */
+stock Weapon_SetPrimaryAmmoType(weapon,type)
+{
+ return SetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoType", type);
+}
+
+/*
+ * Gets the secondary ammo Type (int offset)
+ *
+ * @param weapon Weapon Entity.
+ * @return Secondary ammo type value.
+ */
+stock Weapon_GetSecondaryAmmoType(weapon)
+{
+ return GetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoType");
+}
+
+/*
+ * Sets the secondary ammo Type (int offset)
+ *
+ * @param weapon Weapon Entity.
+ * @param type Secondary ammo type value.
+ */
+stock Weapon_SetSecondaryAmmoType(weapon,type)
+{
+ return SetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoType", type);
+}
+
+/*
+ * Gets the primary clip count of a weapon.
+ *
+ * @param weapon Weapon Entity.
+ * @return Primary Clip count.
+ */
+stock Weapon_GetPrimaryClip(weapon)
+{
+ return GetEntProp(weapon, Prop_Data, "m_iClip1");
+}
+
+/*
+ * Sets the primary clip count of a weapon.
+ *
+ * @param weapon Weapon Entity.
+ * @param value Clip Count value.
+ */
+stock Weapon_SetPrimaryClip(weapon, value)
+{
+ SetEntProp(weapon, Prop_Data, "m_iClip1", value);
+}
+
+/*
+ * Gets the secondary clip count of a weapon.
+ *
+ * @param weapon Weapon Entity.
+ * @return Secondy Clip count.
+ */
+stock Weapon_GetSecondaryClip(weapon)
+{
+ return GetEntProp(weapon, Prop_Data, "m_iClip2");
+}
+
+/*
+ * Sets the secondary clip count of a weapon.
+ *
+ * @param weapon Weapon Entity.
+ * @param value Clip Count value.
+ */
+stock Weapon_SetSecondaryClip(weapon, value)
+{
+ SetEntProp(weapon, Prop_Data, "m_iClip2", value);
+}
+
+/*
+ * Sets the primary & secondary clip count of a weapon.
+ *
+ * @param weapon Weapon Entity.
+ * @param primary Primary Clip Count value.
+ * @param secondary Primary Clip Count value.
+ */
+stock Weapon_SetClips(weapon, primary, secondary)
+{
+ Weapon_SetPrimaryClip(weapon, primary);
+ Weapon_SetSecondaryClip(weapon, secondary);
+}
+
+/*
+ * Gets the primary ammo count of a weapon.
+ * This is only used when the weapon is not carried
+ * by a player to give a player ammo when he picks up
+ * the weapon.
+ *
+ * @param weapon Weapon Entity.
+ * @return Primary Ammo Count.
+ */
+stock Weapon_GetPrimaryAmmoCount(weapon)
+{
+ return GetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoCount");
+}
+
+/*
+ * Sets the primary ammo count of a weapon.
+ * This is only used when the weapon is not carried
+ * by a player to give a player ammo when he picks up
+ * the weapon.
+ *
+ * @param weapon Weapon Entity.
+ * @param value Primary Ammo Count.
+ * @noreturn
+ */
+stock Weapon_SetPrimaryAmmoCount(weapon, value)
+{
+ SetEntProp(weapon, Prop_Data, "m_iPrimaryAmmoCount", value);
+}
+
+/*
+ * Gets the secondary ammo count of a weapon.
+ * This is only used when the weapon is not carried
+ * by a player to give a player ammo when he picks up
+ * the weapon.
+ *
+ * @param weapon Weapon Entity.
+ * @return Secondary Ammo Count.
+ */
+stock Weapon_GetSecondaryAmmoCount(weapon)
+{
+ return GetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoCount");
+}
+
+/*
+ * Sets the secodary ammo count of a weapon.
+ * This is only used when the weapon is not carried
+ * by a player to give a player ammo when he picks up
+ * the weapon.
+ *
+ * @param weapon Weapon Entity.
+ * @param value Secondary Ammo Count.
+ * @noreturn
+ */
+stock Weapon_SetSecondaryAmmoCount(weapon, value)
+{
+ SetEntProp(weapon, Prop_Data, "m_iSecondaryAmmoCount", value);
+}
+
+/*
+ * Sets both, the primary & the secondary ammo count of a weapon.
+ * This is only used when the weapon is not carried
+ * by a player to give a player ammo when he picks up
+ * the weapon.
+ *
+ * @param weapon Weapon Entity.
+ * @value primary Primary Ammo Count.
+ * @value secondary Secondary Ammo Count.
+ * @noreturn
+ */
+stock Weapon_SetAmmoCounts(weapon, primary, secondary)
+{
+ Weapon_SetPrimaryAmmoCount(weapon, primary);
+ Weapon_SetSecondaryAmmoCount(weapon, secondary);
+}
+
+/*
+ * Gets the Model Index of the weapon's view model.
+ *
+ * @param weapon Weapon Entity.
+ * @return View Model Index.
+ */
+stock Weapon_GetViewModelIndex(weapon)
+{
+ return GetEntProp(weapon, Prop_Data, "m_nViewModelIndex");
+}
+
+/*
+ * Sets the Model Index of the weapon's view model.
+ * You can get the Model Index by precaching a model with PrecacheModel().
+ *
+ * @param weapon Weapon Entity.
+ * @param index Model Index.
+ * @noreturn
+ */
+stock Weapon_SetViewModelIndex(weapon, index)
+{
+ SetEntProp(weapon, Prop_Data, "m_nViewModelIndex", index);
+ ChangeEdictState(weapon, FindDataMapOffs(weapon, "m_nViewModelIndex"));
+}
+
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/world.inc b/sourcemod-1.5-dev/scripting/include/smlib/world.inc
new file mode 100644
index 0000000..a9b47b5
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/smlib/world.inc
@@ -0,0 +1,17 @@
+#if defined _smlib_world_included
+ #endinput
+#endif
+#define _smlib_world_included
+
+#include <sourcemod>
+
+/*
+ * Gets the world's max size
+ *
+ * @param vec Vector buffer
+ * @noreturn
+ */
+stock World_GetMaxs(Float:vec[3]) {
+
+ GetEntPropVector(0, Prop_Data, "m_WorldMaxs", vec);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/sorting.inc b/sourcemod-1.5-dev/scripting/include/sorting.inc
new file mode 100644
index 0000000..50ac310
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sorting.inc
@@ -0,0 +1,176 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+
+#if defined _sorting_included
+ #endinput
+#endif
+#define _sorting_included
+
+/**
+ * Contains sorting orders.
+ */
+enum SortOrder
+{
+ Sort_Ascending = 0, /**< Ascending order */
+ Sort_Descending = 1, /**< Descending order */
+ Sort_Random = 2 /**< Random order */
+};
+
+/**
+ * Data types for ADT Array Sorts
+ */
+enum SortType
+{
+ Sort_Integer = 0,
+ Sort_Float,
+ Sort_String,
+};
+
+/**
+ * Sorts an array of integers.
+ *
+ * @param array Array of integers to sort in-place.
+ * @param array_size Size of the array.
+ * @param order Sorting order to use.
+ * @noreturn
+ */
+native SortIntegers(array[], array_size, SortOrder:order = Sort_Ascending);
+
+/**
+ * Sorts an array of float point numbers.
+ *
+ * @param array Array of floating point numbers to sort in-place.
+ * @param array_size Size of the array.
+ * @param order Sorting order to use.
+ * @noreturn
+ */
+native SortFloats(Float:array[], array_size, SortOrder:order = Sort_Ascending);
+
+/**
+ * Sorts an array of strings.
+ *
+ * @param array Array of strings to sort in-place.
+ * @param array_size Size of the array.
+ * @param order Sorting order to use.
+ * @noreturn
+ */
+native SortStrings(String:array[][], array_size, SortOrder:order = Sort_Ascending);
+
+/**
+ * Sort comparison function for 1D array elements.
+ * @note You may need to use explicit tags in order to use data properly.
+ *
+ * @param elem1 First element to compare.
+ * @param elem2 Second element to compare.
+ * @param array Array that is being sorted (order is undefined).
+ * @param hndl Handle optionally passed in while sorting.
+ * @return -1 if first should go before second
+ * 0 if first is equal to second
+ * 1 if first should go after second
+ */
+functag public SortFunc1D(elem1, elem2, const array[], Handle:hndl);
+
+/**
+ * Sorts a custom 1D array. You must pass in a comparison function.
+ *
+ * @param array Array to sort.
+ * @param array_size Size of the array to sort.
+ * @param sortfunc Sort function.
+ * @param hndl Optional Handle to pass through the comparison calls.
+ * @noreturn
+ */
+native SortCustom1D(array[], array_size, SortFunc1D:sortfunc, Handle:hndl=INVALID_HANDLE);
+
+/**
+ * Sort comparison function for 2D array elements (sub-arrays).
+ * @note You may need to use explicit tags in order to use data properly.
+ *
+ * @param elem1 First array to compare.
+ * @param elem2 Second array to compare.
+ * @param array Array that is being sorted (order is undefined).
+ * @param hndl Handle optionally passed in while sorting.
+ * @return -1 if first should go before second
+ * 0 if first is equal to second
+ * 1 if first should go after second
+ */
+funcenum SortFunc2D
+{
+ public(elem1[], elem2[], const array[][], Handle:hndl),
+ public(String:elem1[], String:elem2[], const String:array[][], Handle:hndl),
+};
+
+/**
+ * Sorts a custom 2D array. You must pass in a comparison function.
+ *
+ * @param array Array to sort.
+ * @param array_size Size of the major array to sort (first index, outermost).
+ * @param sortfunc Sort comparison function to use.
+ * @param hndl Optional Handle to pass through the comparison calls.
+ * @noreturn
+ */
+native SortCustom2D(array[][], array_size, SortFunc2D:sortfunc, Handle:hndl=INVALID_HANDLE);
+
+/**
+ * Sort an ADT Array. Specify the type as Integer, Float, or String.
+ *
+ * @param array Array Handle to sort
+ * @param order Sort order to use, same as other sorts.
+ * @param type Data type stored in the ADT Array
+ * @noreturn
+ */
+native SortADTArray(Handle:array, SortOrder:order, SortType:type);
+
+/**
+ * Sort comparison function for ADT Array elements. Function provides you with
+ * indexes currently being sorted, use ADT Array functions to retrieve the
+ * index values and compare.
+ *
+ * @param index1 First index to compare.
+ * @param index2 Second index to compare.
+ * @param array Array that is being sorted (order is undefined).
+ * @param hndl Handle optionally passed in while sorting.
+ * @return -1 if first should go before second
+ * 0 if first is equal to second
+ * 1 if first should go after second
+ */
+functag public SortFuncADTArray(index1, index2, Handle:array, Handle:hndl);
+
+/**
+ * Custom sorts an ADT Array. You must pass in a comparison function.
+ *
+ * @param array Array Handle to sort
+ * @param sortfunc Sort comparision function to use
+ * @param hndl Optional Handle to pass through the comparison calls.
+ * @noreturn
+ */
+native SortADTArrayCustom(Handle:array, SortFuncADTArray:sortfunc, Handle:hndl=INVALID_HANDLE); \ No newline at end of file
diff --git a/sourcemod-1.5-dev/scripting/include/sourcemod.inc b/sourcemod-1.5-dev/scripting/include/sourcemod.inc
new file mode 100644
index 0000000..dec146d
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/sourcemod.inc
@@ -0,0 +1,682 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _sourcemod_included
+ #endinput
+#endif
+#define _sourcemod_included
+
+/**
+ * Plugin public information.
+ */
+struct Plugin
+{
+ const String:name[], /**< Plugin Name */
+ const String:description[], /**< Plugin Description */
+ const String:author[], /**< Plugin Author */
+ const String:version[], /**< Plugin Version */
+ const String:url[], /**< Plugin URL */
+};
+
+#include <core>
+#include <float>
+#include <vector>
+#include <string>
+#include <handles>
+#include <functions>
+#include <files>
+#include <logging>
+#include <timers>
+#include <admin>
+#include <keyvalues>
+#include <dbi>
+#include <lang>
+#include <sorting>
+#include <textparse>
+#include <clients>
+#include <console>
+#include <events>
+#include <bitbuffer>
+#include <protobuf>
+#include <usermessages>
+#include <menus>
+#include <halflife>
+#include <adt>
+#include <banning>
+#include <commandfilters>
+#include <nextmap>
+
+enum APLRes
+{
+ APLRes_Success = 0, /**< Plugin should load */
+ APLRes_Failure, /**< Plugin shouldn't load and should display an error */
+ APLRes_SilentFailure /**< Plugin shouldn't load but do so silently */
+};
+
+/**
+ * Declare this as a struct in your plugin to expose its information.
+ * Example:
+ *
+ * public Plugin:myinfo =
+ * {
+ * name = "My Plugin",
+ * //etc
+ * };
+ */
+public Plugin:myinfo;
+
+/**
+ * Called when the plugin is fully initialized and all known external references
+ * are resolved. This is only called once in the lifetime of the plugin, and is
+ * paired with OnPluginEnd().
+ *
+ * If any run-time error is thrown during this callback, the plugin will be marked
+ * as failed.
+ *
+ * It is not necessary to close any handles or remove hooks in this function.
+ * SourceMod guarantees that plugin shutdown automatically and correctly releases
+ * all resources.
+ *
+ * @noreturn
+ */
+forward OnPluginStart();
+
+/**
+ * @deprecated Use AskPluginLoad2() instead.
+ * If a plugin contains both AskPluginLoad() and AskPluginLoad2(), the former will
+ * not be called, but old plugins with only AskPluginLoad() will work.
+ */
+#pragma deprecated Use AskPluginLoad2() instead
+forward bool:AskPluginLoad(Handle:myself, bool:late, String:error[], err_max);
+
+/**
+ * Called before OnPluginStart, in case the plugin wants to check for load failure.
+ * This is called even if the plugin type is "private." Any natives from modules are
+ * not available at this point. Thus, this forward should only be used for explicit
+ * pre-emptive things, such as adding dynamic natives, setting certain types of load
+ * filters (such as not loading the plugin for certain games).
+ *
+ * @note It is not safe to call externally resolved natives until OnPluginStart().
+ * @note Any sort of RTE in this function will cause the plugin to fail loading.
+ * @note If you do not return anything, it is treated like returning success.
+ * @note If a plugin has an AskPluginLoad2(), AskPluginLoad() will not be called.
+ *
+ *
+ * @param myself Handle to the plugin.
+ * @param late Whether or not the plugin was loaded "late" (after map load).
+ * @param error Error message buffer in case load failed.
+ * @param err_max Maximum number of characters for error message buffer.
+ * @return APLRes_Success for load success, APLRes_Failure or APLRes_SilentFailure otherwise
+ */
+forward APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max);
+
+/**
+ * Called when the plugin is about to be unloaded.
+ *
+ * @noreturn
+ */
+forward OnPluginEnd();
+
+/**
+ * Called when the plugin's pause status is changing.
+ *
+ * @param pause True if the plugin is being paused, false otherwise.
+ * @noreturn
+ */
+forward OnPluginPauseChange(bool:pause);
+
+/**
+ * Called before every server frame. Note that you should avoid
+ * doing expensive computations here, and you should declare large
+ * local arrays using 'decl' instead of 'new'.
+ */
+forward OnGameFrame();
+
+/**
+ * Called when the map is loaded.
+ *
+ * @note This used to be OnServerLoad(), which is now deprecated.
+ * Plugins still using the old forward will work.
+ */
+forward OnMapStart();
+
+/**
+ * Called right before a map ends.
+ */
+forward OnMapEnd();
+
+/**
+ * Called when the map has loaded, servercfgfile (server.cfg) has been
+ * executed, and all plugin configs are done executing. This is the best
+ * place to initialize plugin functions which are based on cvar data.
+ *
+ * @note This will always be called once and only once per map. It will be
+ * called after OnMapStart().
+ *
+ * @noreturn
+ */
+forward OnConfigsExecuted();
+
+/**
+ * This is called once, right after OnMapStart() but any time before
+ * OnConfigsExecuted(). It is called after the "exec sourcemod.cfg"
+ * command and all AutoExecConfig() exec commands have been added to
+ * the ServerCommand() buffer.
+ *
+ * If you need to load per-map settings that override default values,
+ * adding commands to the ServerCommand() buffer here will guarantee
+ * that they're set before OnConfigsExecuted().
+ *
+ * Unlike OnMapStart() and OnConfigsExecuted(), this is not called on
+ * late loads that occur after OnMapStart().
+ *
+ * @noreturn
+ */
+forward OnAutoConfigsBuffered();
+
+/**
+ * @deprecated Use OnConfigsExecuted() instead.
+ */
+#pragma deprecated Use OnConfigsExecuted() instead
+forward OnServerCfg();
+
+/**
+ * Called after all plugins have been loaded. This is called once for
+ * every plugin. If a plugin late loads, it will be called immediately
+ * after OnPluginStart().
+ */
+forward OnAllPluginsLoaded();
+
+/**
+ * Returns the calling plugin's Handle.
+ *
+ * @return Handle of the calling plugin.
+ */
+native Handle:GetMyHandle();
+
+/**
+ * Returns an iterator that can be used to search through plugins.
+ *
+ * @return Handle to iterate with. Must be closed via
+ * CloseHandle().
+ * @error Invalid Handle.
+ */
+native Handle:GetPluginIterator();
+
+/**
+ * Returns whether there are more plugins available in the iterator.
+ *
+ * @param iter Handle to the plugin iterator.
+ * @return True on more plugins, false otherwise.
+ * @error Invalid Handle.
+ */
+native bool:MorePlugins(Handle:iter);
+
+/**
+ * Returns the current plugin in the iterator and advances the iterator.
+ *
+ * @param iter Handle to the plugin iterator.
+ * @return Current plugin the iterator is at, before
+ * the iterator is advanced.
+ * @error Invalid Handle.
+ */
+native Handle:ReadPlugin(Handle:iter);
+
+/**
+ * Returns a plugin's status.
+ *
+ * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin).
+ * @return Status code for the plugin.
+ * @error Invalid Handle.
+ */
+native PluginStatus:GetPluginStatus(Handle:plugin);
+
+/**
+ * Retrieves a plugin's file name relative to the plugins folder.
+ *
+ * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin).
+ * @param buffer Buffer to the store the file name.
+ * @param maxlength Maximum length of the name buffer.
+ * @noreturn
+ * @error Invalid Handle.
+ */
+native GetPluginFilename(Handle:plugin, String:buffer[], maxlength);
+
+/**
+ * Retrieves whether or not a plugin is being debugged.
+ *
+ * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin).
+ * @return True if being debugged, false otherwise.
+ * @error Invalid Handle.
+ */
+native bool:IsPluginDebugging(Handle:plugin);
+
+/**
+ * Retrieves a plugin's public info.
+ *
+ * @param plugin Plugin Handle (INVALID_HANDLE uses the calling plugin).
+ * @param info Plugin info property to retrieve.
+ * @param buffer Buffer to store info in.
+ * @param maxlength Maximum length of buffer.
+ * @return True on success, false if property is not available.
+ * @error Invalid Handle.
+ */
+native bool:GetPluginInfo(Handle:plugin, PluginInfo:info, String:buffer[], maxlength);
+
+/**
+ * Finds a plugin by its order in the list from the "plugins list" server
+ * "sm" command. You should not use this function to loop through all plugins,
+ * use the iterator instead. Looping through all plugins using this native
+ * is O(n^2), whereas using the iterator is O(n).
+ *
+ * @param order_num Number of the plugin as it appears in "sm plugins list".
+ * @return Plugin Handle on success, INVALID_HANDLE if no plugin
+ * matches the given number.
+ */
+native Handle:FindPluginByNumber(order_num);
+
+/**
+ * Causes the plugin to enter a failed state. An error will be thrown and
+ * the plugin will be paused until it is unloaded or reloaded.
+ *
+ * For backwards compatibility, if no extra arguments are passed, no
+ * formatting is applied. If one or more additional arguments is passed,
+ * the string is formatted using Format(). If any errors are encountered
+ * during formatting, both the format specifier string and an additional
+ * error message are written.
+ *
+ * This function does not return, and no further code in the plugin is
+ * executed.
+ *
+ * @param string Format specifier string.
+ * @param ... Formatting arguments.
+ * @noreturn
+ * @error Always throws SP_ERROR_ABORT.
+ */
+native SetFailState(const String:string[], any:...);
+
+/**
+ * Aborts the current callback and throws an error. This function
+ * does not return in that no code is executed following it.
+ *
+ * @param fmt String format.
+ * @param ... Format arguments.
+ * @noreturn
+ * @error Always!
+ */
+native ThrowError(const String:fmt[], any:...);
+
+/**
+ * Gets the system time as a unix timestamp.
+ *
+ * @param bigStamp Optional array to store the 64bit timestamp in.
+ * @return 32bit timestamp (number of seconds since unix epoch).
+ */
+native GetTime(bigStamp[2]={0,0});
+
+/**
+ * Produces a date and/or time string value for a timestamp.
+ *
+ * See this URL for valid parameters:
+ * http://cplusplus.com/reference/clibrary/ctime/strftime.html
+ *
+ * @param buffer Destination string buffer.
+ * @param maxlength Maximum length of output string buffer.
+ * @param format Formatting rules (passing NULL_STRING will use the rules defined in sm_datetime_format).
+ * @param stamp Optional time stamp.
+ * @noreturn
+ * @error Buffer too small or invalid time format.
+ */
+native FormatTime(String:buffer[], maxlength, const String:format[], stamp=-1);
+
+/**
+ * Loads a game config file.
+ *
+ * @param file File to load. The path must be relative to the 'gamedata' folder under the config folder
+ * and the extension should be omitted.
+ * @return A handle to the game config file or INVALID_HANDLE in failure.
+ */
+native Handle:LoadGameConfigFile(const String:file[]);
+
+/**
+ * Returns an offset value.
+ *
+ * @param gc Game config handle.
+ * @param key Key to retrieve from the offset section.
+ * @return An offset, or -1 on failure.
+ */
+native GameConfGetOffset(Handle:gc, const String:key[]);
+
+/**
+ * Gets the value of a key from the "Keys" section.
+ *
+ * @param gc Game config handle.
+ * @param key Key to retrieve from the Keys section.
+ * @param buffer Destination string buffer.
+ * @param maxlen Maximum length of output string buffer.
+ * @return True if key existed, false otherwise.
+ */
+native bool:GameConfGetKeyValue(Handle:gc, const String:key[], String:buffer[], maxlen);
+
+/**
+ * Finds an address calculation in a GameConfig file,
+ * performs LoadFromAddress on it as appropriate, then returns the final address.
+ *
+ * @param gameconf GameConfig Handle, or INVALID_HANDLE to use sdktools.games.txt.
+ * @param name Name of the property to find.
+ * @return An address calculated on success, or 0 on failure.
+ */
+native Address:GameConfGetAddress(Handle:gameconf, const String:name[]);
+
+/**
+ * Returns the operating system's "tick count," which is a number of
+ * milliseconds since the operating system loaded. This can be used
+ * for basic benchmarks.
+ *
+ * @return Tick count in milliseconds.
+ */
+native GetSysTickCount();
+
+/**
+ * Specifies that the given config file should be executed after plugin load.
+ * OnConfigsExecuted() will not be called until the config file has executed,
+ * but it will be called if the execution fails.
+ *
+ * @param autoCreate If true, and the config file does not exist, such a config
+ * file will be automatically created and populated with
+ * information from the plugin's registered cvars.
+ * @param name Name of the config file, excluding the .cfg extension.
+ * If empty, <plugin.filename.cfg> is assumed.
+ * @param folder Folder under cfg/ to use. By default this is "sourcemod."
+ * @noreturn
+ */
+native AutoExecConfig(bool:autoCreate=true, const String:name[]="", const String:folder[]="sourcemod");
+
+/**
+ * Registers a library name for identifying as a dependency to
+ * other plugins.
+ *
+ * @param name Library name.
+ * @noreturn
+ */
+native RegPluginLibrary(const String:name[]);
+
+/**
+ * Returns whether a library exists. This function should be considered
+ * expensive; it should only be called on plugin to determine availability
+ * of resources. Use OnLibraryAdded()/OnLibraryRemoved() to detect changes
+ * in optional resources.
+ *
+ * @param name Library name of a plugin or extension.
+ * @return True if exists, false otherwise.
+ */
+native bool:LibraryExists(const String:name[]);
+
+/**
+ * Returns the status of an extension, by filename.
+ *
+ * @param name Extension name (like "sdktools.ext").
+ * @param error Optional error message buffer.
+ * @param maxlength Length of optional error message buffer.
+ * @return -2 if the extension was not found.
+ * -1 if the extension was found but failed to load.
+ * 0 if the extension loaded but reported an error.
+ * 1 if the extension is running without error.
+ */
+native GetExtensionFileStatus(const String:name[], String:error[]="", maxlength=0);
+
+/**
+ * Called after a library is added that the current plugin references
+ * optionally. A library is either a plugin name or extension name, as
+ * exposed via its include file.
+ *
+ * @param name Library name.
+ */
+forward OnLibraryAdded(const String:name[]);
+
+/**
+ * Called right before a library is removed that the current plugin references
+ * optionally. A library is either a plugin name or extension name, as
+ * exposed via its include file.
+ *
+ * @param name Library name.
+ */
+forward OnLibraryRemoved(const String:name[]);
+
+#define MAPLIST_FLAG_MAPSFOLDER (1<<0) /**< On failure, use all maps in the maps folder. */
+#define MAPLIST_FLAG_CLEARARRAY (1<<1) /**< If an input array is specified, clear it before adding. */
+#define MAPLIST_FLAG_NO_DEFAULT (1<<2) /**< Do not read "default" or "mapcyclefile" on failure. */
+
+/**
+ * Loads a map list to an ADT Array.
+ *
+ * A map list is a list of maps from a file. SourceMod allows easy configuration of
+ * maplists through addons/sourcemod/configs/maplists.cfg. Each entry is given a
+ * name and a file (for example, "rtv" => "rtv.cfg"), or a name and a redirection
+ * (for example, "rtv" => "default"). This native will read a map list entry,
+ * cache the file, and return the list of maps it holds.
+ *
+ * Serial change numbers are used to identify if a map list has changed. Thus, if
+ * you pass a serial change number and it's equal to what SourceMod currently knows
+ * about the map list, then SourceMod won't reparse the file.
+ *
+ * If the maps end up being read from the maps folder (MAPLIST_FLAG_MAPSFOLDER), they
+ * are automatically sorted in alphabetical, ascending order.
+ *
+ * Arrays created by this function are temporary and must be freed via CloseHandle().
+ * Modifying arrays created by this function will not affect future return values or
+ * or the contents of arrays returned to other plugins.
+ *
+ * @param array Array to store the map list. If INVALID_HANDLE, a new blank
+ * array will be created. The blocksize should be at least 16;
+ * otherwise results may be truncated. Items are added to the array
+ * as strings. The array is never checked for duplicates, and it is
+ * not read beforehand. Only the serial number is used to detect
+ * changes.
+ * @param serial Serial number to identify last known map list change. If -1, the
+ * the value will not be checked. If the map list has since changed,
+ * the serial is updated (even if -1 was passed). If there is an error
+ * finding a valid maplist, then the serial is set to -1.
+ * @param str Config name, or "default" for the default map list. Config names
+ * should be somewhat descriptive. For example, the admin menu uses
+ * a config name of "admin menu". The list names can be configured
+ * by users in addons/sourcemod/configs/maplists.cfg.
+ * @param flags MAPLIST_FLAG flags.
+ * @return On failure:
+ * INVALID_HANDLE is returned, the serial is set to -1, and the input
+ * array (if any) is left unchanged.
+ * On no change:
+ INVALID_HANDLE is returned, the serial is unchanged, and the input
+ array (if any) is left unchanged.
+ * On success:
+ * A valid array Handle is returned, containing at least one map string.
+ * If an array was passed, the return value is equal to the passed Array
+ * Handle. If the passed array was not cleared, it will have grown by at
+ * least one item. The serial number is updated to a positive number.
+ * @error Invalid array Handle that is not INVALID_HANDLE.
+ */
+native Handle:ReadMapList(Handle:array=INVALID_HANDLE,
+ &serial=-1,
+ const String:str[]="default",
+ flags=MAPLIST_FLAG_CLEARARRAY);
+
+/**
+ * Makes a compatibility binding for map lists. For example, if a function previously used
+ * "clam.cfg" for map lists, this function will insert a "fake" binding to "clam.cfg" that
+ * will be overridden if it's in the maplists.cfg file.
+ *
+ * @param name Configuration name that would be used with ReadMapList().
+ * @param file Default file to use.
+ * @noreturn
+ */
+native SetMapListCompatBind(const String:name[], const String:file[]);
+
+/**
+ * Called when a client has sent chat text. This must return either true or
+ * false to indicate that a client is or is not spamming the server.
+ *
+ * The return value is a hint only. Core or another plugin may decide
+ * otherwise.
+ *
+ * @param client Client index. The server (0) will never be passed.
+ * @return True if client is spamming the server, false otherwise.
+ */
+forward bool:OnClientFloodCheck(client);
+
+/**
+ * Called after a client's flood check has been computed. This can be used
+ * by antiflood algorithms to decay/increase flooding weights.
+ *
+ * Since the result from "OnClientFloodCheck" isn't guaranteed to be the
+ * final result, it is generally a good idea to use this to play with other
+ * algorithms nicely.
+ *
+ * @param client Client index. The server (0) will never be passed.
+ * @param blocked True if client flooded last "say", false otherwise.
+ * @noreturn
+ */
+forward OnClientFloodResult(client, bool:blocked);
+
+/**
+ * Feature types.
+ */
+enum FeatureType
+{
+ /**
+ * A native function call.
+ */
+ FeatureType_Native,
+
+ /**
+ * A named capability. This is distinctly different from checking for a
+ * native, because the underlying functionality could be enabled on-demand
+ * to improve loading time. Thus a native may appear to exist, but it might
+ * be part of a set of features that are not compatible with the current game
+ * or version of SourceMod.
+ */
+ FeatureType_Capability
+};
+
+/**
+ * Feature statuses.
+ */
+enum FeatureStatus
+{
+ /**
+ * Feature is available for use.
+ */
+ FeatureStatus_Available,
+
+ /**
+ * Feature is not available.
+ */
+ FeatureStatus_Unavailable,
+
+ /**
+ * Feature is not known at all.
+ */
+ FeatureStatus_Unknown
+};
+
+/**
+ * Returns whether "GetFeatureStatus" will work. Using this native
+ * or this function will not cause SourceMod to fail loading on older versions,
+ * however, GetFeatureStatus will only work if this function returns true.
+ *
+ * @return True if GetFeatureStatus will work, false otherwise.
+ */
+stock bool:CanTestFeatures()
+{
+ return LibraryExists("__CanTestFeatures__");
+}
+
+/**
+ * Returns whether a feature exists, and if so, whether it is usable.
+ *
+ * @param type Feature type.
+ * @param name Feature name.
+ * @return Feature status.
+ */
+native FeatureStatus:GetFeatureStatus(FeatureType:type, const String:name[]);
+
+/**
+ * Requires that a given feature is available. If it is not, SetFailState()
+ * is called with the given message.
+ *
+ * @param type Feature type.
+ * @param name Feature name.
+ * @param fmt Message format string, or empty to use default.
+ * @param ... Message format parameters, if any.
+ * @noreturn
+ */
+native RequireFeature(FeatureType:type, const String:name[],
+ const String:fmt[]="", any:...);
+
+/**
+ * Represents how many bytes we can read from an address with one load
+ */
+enum NumberType
+{
+ NumberType_Int8,
+ NumberType_Int16,
+ NumberType_Int32
+};
+
+enum Address
+{
+ Address_Null = 0, //a typical invalid result when an address lookup fails
+ Address_MinimumValid = 0x10000 //addresses below this value are considered invalid to use for Load/Store
+};
+
+/**
+ * Load up to 4 bytes from a memory address.
+ *
+ * @param addr Address to a memory location.
+ * @param size How many bytes should be read.
+ * @return The value that is stored at that address.
+ */
+native LoadFromAddress(Address:addr, NumberType:size);
+
+/**
+ * Store up to 4 bytes to a memory address.
+ *
+ * @param addr Address to a memory location.
+ * @param data Value to store at the address.
+ * @param size How many bytes should be written.
+ * @noreturn
+ */
+native StoreToAddress(Address:addr, data, NumberType:size);
+
+#include <helpers>
+#include <entity>
+#include <entity_prop_stocks>
+
diff --git a/sourcemod-1.5-dev/scripting/include/string.inc b/sourcemod-1.5-dev/scripting/include/string.inc
new file mode 100644
index 0000000..a06b924
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/string.inc
@@ -0,0 +1,559 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _string_included
+ #endinput
+#endif
+#define _string_included
+
+/**
+ * @global Unless otherwise noted, all string functions which take in a
+ * writable buffer and maximum length should have the null terminator INCLUDED
+ * in the length. This means that this is valid:
+ * strcopy(string, sizeof(string), ...)
+ */
+
+/**
+ * Calculates the length of a string.
+ *
+ * @param str String to check.
+ * @return Number of valid character bytes in the string.
+ */
+native strlen(const String:str[]);
+
+/**
+ * Tests whether a string is found inside another string.
+ *
+ * @param str String to search in.
+ * @param substr Substring to find inside the original string.
+ * @param caseSensitive If true (default), search is case sensitive.
+ * If false, search is case insensitive.
+ * @return -1 on failure (no match found). Any other value
+ * indicates a position in the string where the match starts.
+ */
+native StrContains(const String:str[], const String:substr[], bool:caseSensitive=true);
+
+/**
+ * Compares two strings lexographically.
+ *
+ * @param str1 First string (left).
+ * @param str2 Second string (right).
+ * @param caseSensitive If true (default), comparison is case sensitive.
+ * If false, comparison is case insensitive.
+ * @return -1 if str1 < str2
+ * 0 if str1 == str2
+ * 1 if str1 > str2
+ */
+native strcmp(const String:str1[], const String:str2[], bool:caseSensitive=true);
+
+/**
+ * Compares two strings parts lexographically.
+ *
+ * @param str1 First string (left).
+ * @param str2 Second string (right).
+ * @param num Number of characters to compare.
+ * @param caseSensitive If true (default), comparison is case sensitive.
+ * If false, comparison is case insensitive.
+ * @return -1 if str1 < str2
+ * 0 if str1 == str2
+ * 1 if str1 > str2
+ */
+native strncmp(const String:str1[], const String:str2[], num, bool:caseSensitive=true);
+
+/**
+ * Backwards compatible stock - StrCompare is now strcmp
+ * @deprecated Renamed to strcmp
+ */
+#pragma deprecated Use strcmp() instead
+stock StrCompare(const String:str1[], const String:str2[], bool:caseSensitive=true)
+{
+ return strcmp(str1, str2, caseSensitive);
+}
+
+/**
+ * Returns whether two strings are equal.
+ *
+ * @param str1 First string (left).
+ * @param str2 Second string (right).
+ * @param caseSensitive If true (default), comparison is case sensitive.
+ * If false, comparison is case insensitive.
+ * @return True if equal, false otherwise.
+ */
+stock bool:StrEqual(const String:str1[], const String:str2[], bool:caseSensitive=true)
+{
+ return (strcmp(str1, str2, caseSensitive) == 0);
+}
+
+/**
+ * Copies one string to another string.
+ * @note If the destination buffer is too small to hold the source string, the
+ * destination will be truncated.
+ *
+ * @param dest Destination string buffer to copy to.
+ * @param destLen Destination buffer length (includes null terminator).
+ * @param source Source string buffer to copy from.
+ * @return Number of cells written.
+ */
+native strcopy(String:dest[], destLen, const String:source[]);
+
+/**
+ * Backwards compatibility stock - use strcopy
+ * @deprecated Renamed to strcopy
+ */
+#pragma deprecated Use strcopy() instead
+stock StrCopy(String:dest[], destLen, const String:source[])
+{
+ return strcopy(dest, destLen, source);
+}
+
+/**
+ * Formats a string according to the SourceMod format rules (see documentation).
+ *
+ * @param buffer Destination string buffer.
+ * @param maxlength Maximum length of output string buffer.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @return Number of cells written.
+ */
+native Format(String:buffer[], maxlength, const String:format[], any:...);
+
+/**
+ * Formats a string according to the SourceMod format rules (see documentation).
+ * @note This is the same as Format(), except none of the input buffers can
+ * overlap the same memory as the output buffer. Since this security
+ * check is removed, it is slightly faster.
+ *
+ * @param buffer Destination string buffer.
+ * @param maxlength Maximum length of output string buffer.
+ * @param format Formatting rules.
+ * @param ... Variable number of format parameters.
+ * @return Number of cells written.
+ */
+native FormatEx(String:buffer[], maxlength, const String:format[], any:...);
+
+/**
+ * Formats a string according to the SourceMod format rules (see documentation).
+ * @note This is the same as Format(), except it grabs parameters from a
+ * parent parameter stack, rather than a local. This is useful for
+ * implementing your own variable argument functions.
+ *
+ * @param buffer Destination string buffer.
+ * @param maxlength Maximum length of output string buffer.
+ * @param format Formatting rules.
+ * @param varpos Argument number which contains the '...' symbol.
+ * Note: Arguments start at 1.
+ * @return Number of bytes written.
+ */
+native VFormat(String:buffer[], maxlength, const String:format[], varpos);
+
+/**
+ * Converts a string to an integer.
+ *
+ * @param str String to convert.
+ * @param nBase Numerical base to use. 10 is default.
+ * @return Integer conversion of string, or 0 on failure.
+ */
+native StringToInt(const String:str[], nBase=10);
+
+/**
+ * Converts a string to an integer with some more options.
+ *
+ * @param str String to convert.
+ * @param result Variable to store the result in.
+ * @param nBase Numerical base to use. 10 is default.
+ * @return Number of characters consumed.
+ */
+native StringToIntEx(const String:str[], &result, nBase=10);
+
+/**
+ * Converts an integer to a string.
+ *
+ * @param num Integer to convert.
+ * @param str Buffer to store string in.
+ * @param maxlength Maximum length of string buffer.
+ * @return Number of cells written to buffer.
+ */
+native IntToString(num, String:str[], maxlength);
+
+/**
+ * Converts a string to a floating point number.
+ *
+ * @param str String to convert to a foat.
+ * @return Floating point result, or 0.0 on error.
+ */
+native Float:StringToFloat(const String:str[]);
+
+/**
+ * Converts a string to a floating point number with some more options.
+ *
+ * @param str String to convert to a foat.
+ * @param result Variable to store result in.
+ * @return Number of characters consumed.
+ */
+native StringToFloatEx(const String:str[], &Float:result);
+
+/**
+ * Converts a floating point number to a string.
+ *
+ * @param num Floating point number to convert.
+ * @param str Buffer to store string in.
+ * @param maxlength Maximum length of string buffer.
+ * @return Number of cells written to buffer.
+ */
+native FloatToString(Float:num, String:str[], maxlength);
+
+/**
+ * Finds the first "argument" in a string; either a set of space
+ * terminated characters, or a fully quoted string. After the
+ * argument is found, whitespace is read until the next portion
+ * of the string is reached. If nothing remains, -1 is returned.
+ * Otherwise, the index to the first character is returned.
+ *
+ * @param source Source input string.
+ * @param arg Stores argument read from string.
+ * @param argLen Maximum length of argument buffer.
+ * @return Index to next piece of string, or -1 if none.
+ */
+native BreakString(const String:source[], String:arg[], argLen);
+
+/**
+ * Backwards compatibility stock - use BreakString
+ * @deprecated Renamed to BreakString.
+ */
+#pragma deprecated Use BreakString() instead
+stock StrBreak(const String:source[], String:arg[], argLen)
+{
+ return BreakString(source, arg, argLen);
+}
+
+/**
+ * Removes whitespace characters from the beginning and end of a string.
+ *
+ * @param str The string to trim.
+ * @return Number of bytes written (UTF-8 safe).
+ */
+native TrimString(String:str[]);
+
+/**
+ * Returns text in a string up until a certain character sequence is reached.
+ *
+ * @param source Source input string.
+ * @param split A string which specifies a search point to break at.
+ * @param part Buffer to store string part.
+ * @param partLen Maximum length of the string part buffer.
+ * @return -1 if no match was found; otherwise, an index into source
+ * marking the first index after the searched text. The
+ * index is always relative to the start of the input string.
+ */
+native SplitString(const String:source[], const String:split[], String:part[], partLen);
+
+/**
+ * Given a string, replaces all occurrences of a search string with a
+ * replacement string.
+ *
+ * @param text String to perform search and replacements on.
+ * @param maxlength Maximum length of the string buffer.
+ * @param search String to search for.
+ * @param replace String to replace the search string with.
+ * @param caseSensitive If true (default), search is case sensitive.
+ * @return Number of replacements that were performed.
+ */
+native ReplaceString(String:text[], maxlength, const String:search[], const String:replace[], bool:caseSensitive=true);
+
+/**
+ * Given a string, replaces the first occurrence of a search string with a
+ * replacement string.
+ *
+ * @param text String to perform search and replacements on.
+ * @param maxlength Maximum length of the string buffer.
+ * @param search String to search for.
+ * @param replace String to replace the search string with.
+ * @param searchLen If higher than -1, its value will be used instead of
+ * a strlen() call on the search parameter.
+ * @param replaceLen If higher than -1, its value will be used instead of
+ * a strlen() call on the replace parameter.
+ * @param caseSensitive If true (default), search is case sensitive.
+ * @return Index into the buffer (relative to the start) from where
+ * the last replacement ended, or -1 if no replacements were
+ * made.
+ */
+native ReplaceStringEx(String:text[], maxlength, const String:search[], const String:replace[], searchLen=-1, replaceLen=-1, bool:caseSensitive=true);
+
+/**
+ * Returns the number of bytes a character is using. This is
+ * for multi-byte characters (UTF-8). For normal ASCII characters,
+ * this will return 1.
+ *
+ * @param source Source input string.
+ * @return Number of bytes the current character uses.
+ */
+native GetCharBytes(const String:source[]);
+
+/**
+ * Returns whether a character is an ASCII alphabet character.
+ *
+ * @note Multi-byte characters will always return false.
+ *
+ * @param chr Character to test.
+ * @return True if character is alphabetical, otherwise false.
+ */
+native bool:IsCharAlpha(chr);
+
+/**
+ * Returns whether a character is numeric.
+ *
+ * @note Multi-byte characters will always return false.
+ *
+ * @param chr Character to test.
+ * @return True if character is numeric, otherwise false.
+ */
+native bool:IsCharNumeric(chr);
+
+/**
+ * Returns whether a character is whitespace.
+ *
+ * @note Multi-byte characters will always return false.
+ *
+ * @param chr Character to test.
+ * @return True if character is whitespace, otherwise false.
+ */
+native bool:IsCharSpace(chr);
+
+/**
+ * Returns if a character is multi-byte or not.
+ *
+ * @param chr Character to test.
+ * @return 0 for a normal 7-bit ASCII character,
+ * otherwise number of bytes in multi-byte character.
+ */
+native IsCharMB(chr);
+
+/**
+ * Returns whether an alphabetic character is uppercase.
+ *
+ * @note Multi-byte characters will always return false.
+ *
+ * @param chr Character to test.
+ * @return True if character is uppercase, otherwise false.
+ */
+native bool:IsCharUpper(chr);
+
+/**
+ * Returns whether an alphabetic character is lowercase.
+ *
+ * @note Multi-byte characters will always return false.
+ *
+ * @param chr Character to test.
+ * @return True if character is lowercase, otherwise false.
+ */
+native bool:IsCharLower(chr);
+
+/**
+ * Strips a quote pair off a string if it exists. That is, the following
+ * replace rule is applied once: ^"(.*)"$ -> ^\1$
+ *
+ * Note that the leading and trailing quotes will only be removed if both
+ * exist. Otherwise, the string is left unmodified. This function should
+ * be considered O(k) (all characters get shifted down).
+ *
+ * @param text String to modify (in place).
+ * @return True if string was modified, false if there was no
+ * set of quotes.
+ */
+native bool:StripQuotes(String:text[]);
+
+/**
+ * Returns an uppercase character to a lowercase character.
+ *
+ * @param chr Characer to convert.
+ * @return Lowercase character on success,
+ * no change on failure.
+ */
+stock CharToUpper(chr)
+{
+ if (IsCharLower(chr))
+ {
+ return (chr & ~(1<<5));
+ }
+ return chr;
+}
+
+/**
+ * Returns a lowercase character to an uppercase character.
+ *
+ * @param chr Characer to convert.
+ * @return Uppercase character on success,
+ * no change on failure.
+ */
+stock CharToLower(chr)
+{
+ if (IsCharUpper(chr))
+ {
+ return (chr | (1<<5));
+ }
+ return chr;
+}
+
+/**
+ * Finds the first occurrence of a character in a string.
+ *
+ * @param str String.
+ * @param c Character to search for.
+ * @param reverse False (default) to search forward, true to search
+ * backward.
+ * @return The index of the first occurrence of the character
+ * in the string, or -1 if the character was not found.
+ */
+stock FindCharInString(const String:str[], c, bool:reverse = false)
+{
+ new i, len
+
+ len = strlen(str);
+
+ if (!reverse)
+ {
+ for (i = 0; i < len; i++)
+ {
+ if (str[i] == c)
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ for (i = len - 1; i >= 0; i--)
+ {
+ if (str[i] == c)
+ {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * Concatenates one string onto another.
+ *
+ * @param buffer String to append to.
+ * @param maxlength Maximum length of entire buffer.
+ * @param source Source string to concatenate.
+ * @return Number of bytes written.
+ */
+stock StrCat(String:buffer[], maxlength, const String:source[])
+{
+ new len = strlen(buffer);
+ if (len >= maxlength)
+ {
+ return 0;
+ }
+
+ return Format(buffer[len], maxlength-len, "%s", source);
+}
+
+/**
+ * Breaks a string into pieces and stores each piece into an array of buffers.
+ *
+ * @param text The string to split.
+ * @param split The string to use as a split delimiter.
+ * @param buffers An array of string buffers (2D array).
+ * @param maxStrings Number of string buffers (first dimension size).
+ * @param maxStringLength Maximum length of each string buffer.
+ * @param copyRemainder False (default) discard excess pieces, true to ignore
+ * delimiters after last piece.
+ * @return Number of strings retrieved.
+ */
+stock ExplodeString(const String:text[], const String:split[], String:buffers[][], maxStrings,
+ maxStringLength, bool:copyRemainder = false)
+{
+ new reloc_idx, idx, total;
+
+ if (maxStrings < 1 || !split[0])
+ {
+ return 0;
+ }
+
+ while ((idx = SplitString(text[reloc_idx], split, buffers[total], maxStringLength)) != -1)
+ {
+ reloc_idx += idx;
+ if (++total == maxStrings)
+ {
+ if (copyRemainder)
+ {
+ strcopy(buffers[total-1], maxStringLength, text[reloc_idx-idx]);
+ }
+ return total;
+ }
+ }
+
+ strcopy(buffers[total++], maxStringLength, text[reloc_idx]);
+
+ return total;
+}
+
+/**
+ * Joins an array of strings into one string, with a "join" string inserted in
+ * between each given string. This function complements ExplodeString.
+ *
+ * @param strings An array of strings.
+ * @param numStrings Number of strings in the array.
+ * @param join The join string to insert between each string.
+ * @param buffer Output buffer to write the joined string to.
+ * @param maxLength Maximum length of the output buffer.
+ * @return Number of bytes written to the output buffer.
+ */
+stock ImplodeStrings(const String:strings[][], numStrings, const String:join[], String:buffer[], maxLength)
+{
+ new total, length, part_length;
+ new join_length = strlen(join);
+ for (new i=0; i<numStrings; i++)
+ {
+ length = strcopy(buffer[total], maxLength-total, strings[i]);
+ total += length;
+ if (length < part_length)
+ {
+ break;
+ }
+ if (i != numStrings - 1)
+ {
+ length = strcopy(buffer[total], maxLength-total, join);
+ total += length;
+ if (length < join_length)
+ {
+ break;
+ }
+ }
+ }
+ return total;
+}
diff --git a/sourcemod-1.5-dev/scripting/include/testing.inc b/sourcemod-1.5-dev/scripting/include/testing.inc
new file mode 100644
index 0000000..28b50e8
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/testing.inc
@@ -0,0 +1,72 @@
+/**
+ * vim: set ts=4 sw=4 tw=99 noet :
+ * =============================================================================
+ * SourceMod (C)2004-2014 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+static TestNumber = 0;
+static String:TestContext[255];
+
+SetTestContext(const String:context[])
+{
+ strcopy(TestContext, sizeof(TestContext), context);
+}
+
+AssertEq(const String:text[], cell1, cell2)
+{
+ TestNumber++;
+ if (cell1 == cell2) {
+ PrintToServer("[%d] %s: %s == %d OK", TestNumber, TestContext, text, cell2);
+ } else {
+ PrintToServer("[%d] %s FAIL: %s should be %d, got %d", TestNumber, TestContext, text, cell2, cell1);
+ ThrowError("test %d (%s in %s) failed", TestNumber, text, TestContext);
+ }
+}
+
+AssertFalse(const String:text[], bool:value)
+{
+ TestNumber++;
+ if (!value) {
+ PrintToServer("[%d] %s: %s == false OK", TestNumber, TestContext, text, value);
+ } else {
+ PrintToServer("[%d] %s FAIL: %s should be false, got true", TestNumber, TestContext, text);
+ ThrowError("test %d (%s in %s) failed", TestNumber, text, TestContext);
+ }
+}
+
+AssertTrue(const String:text[], bool:value)
+{
+ TestNumber++;
+ if (value) {
+ PrintToServer("[%d] %s: %s == true OK", TestNumber, TestContext, text, value);
+ } else {
+ PrintToServer("[%d] %s FAIL: %s should be true, got false", TestNumber, TestContext, text);
+ ThrowError("test %d (%s in %s) failed", TestNumber, text, TestContext);
+ }
+}
diff --git a/sourcemod-1.5-dev/scripting/include/textparse.inc b/sourcemod-1.5-dev/scripting/include/textparse.inc
new file mode 100644
index 0000000..85ef687
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/textparse.inc
@@ -0,0 +1,203 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _textparse_included
+ #endinput
+#endif
+#define _textparse_included
+
+
+/********************************
+ * Everything below describes the SMC Parse, or "SourceMod Configuration" format.
+ * This parser is entirely event based. You must hook events to receive data.
+ * The file format itself is nearly identical to Valve's KeyValues format.
+ ********************************/
+
+/**
+ * Parse result directive.
+ */
+enum SMCResult
+{
+ SMCParse_Continue, /**< Continue parsing */
+ SMCParse_Halt, /**< Stop parsing here */
+ SMCParse_HaltFail /**< Stop parsing and return failure */
+};
+
+/**
+ * Parse error codes.
+ */
+enum SMCError
+{
+ SMCError_Okay = 0, /**< No error */
+ SMCError_StreamOpen, /**< Stream failed to open */
+ SMCError_StreamError, /**< The stream died... somehow */
+ SMCError_Custom, /**< A custom handler threw an error */
+ SMCError_InvalidSection1, /**< A section was declared without quotes, and had extra tokens */
+ SMCError_InvalidSection2, /**< A section was declared without any header */
+ SMCError_InvalidSection3, /**< A section ending was declared with too many unknown tokens */
+ SMCError_InvalidSection4, /**< A section ending has no matching beginning */
+ SMCError_InvalidSection5, /**< A section beginning has no matching ending */
+ SMCError_InvalidTokens, /**< There were too many unidentifiable strings on one line */
+ SMCError_TokenOverflow, /**< The token buffer overflowed */
+ SMCError_InvalidProperty1, /**< A property was declared outside of any section */
+};
+
+/**
+ * Creates a new SMC file format parser. This is used to set parse hooks.
+ *
+ * @return A new Handle to an SMC Parse structure.
+ */
+native Handle:SMC_CreateParser();
+
+/**
+ * Parses an SMC file.
+ *
+ * @param smc A Handle to an SMC Parse structure.
+ * @param file A string containing the file path.
+ * @param line An optional by reference cell to store the last line number read.
+ * @param col An optional by reference cell to store the last column number read.
+ * @return An SMCParseError result.
+ * @error Invalid or corrupt Handle.
+ */
+native SMCError:SMC_ParseFile(Handle:smc, const String:file[], &line=0, &col=0);
+
+/**
+ * Gets an error string for an SMCError code.
+ * @note SMCError_Okay returns false.
+ * @note SMCError_Custom (which is thrown on SMCParse_HaltFail) returns false.
+ *
+ * @param error The SMCParseError code.
+ * @param buffer A string buffer for the error (contents undefined on failure).
+ * @param buf_max The maximum size of the buffer.
+ * @return True on success, false otherwise.
+ */
+native bool:SMC_GetErrorString(SMCError:error, String:buffer[], buf_max);
+
+/**
+ * Called when parsing is started.
+ *
+ * @param smc The SMC Parse Handle.
+ * @noreturn
+ */
+functag public SMC_ParseStart(Handle:smc);
+
+/**
+ * Sets the SMC_ParseStart function of a parse Handle.
+ *
+ * @param smc Handle to an SMC Parse.
+ * @param func SMC_ParseStart function.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native SMC_SetParseStart(Handle:smc, SMC_ParseStart:func);
+
+/**
+ * Called when parsing is halted.
+ *
+ * @param smc The SMC Parse Handle.
+ * @param halted True if abnormally halted, false otherwise.
+ * @param failed True if parsing failed, false otherwise.
+ * @noreturn
+ */
+functag public SMC_ParseEnd(Handle:smc, bool:halted, bool:failed);
+
+/**
+ * Sets the SMC_ParseEnd of a parse handle.
+ *
+ * @param smc Handle to an SMC Parse.
+ * @param func SMC_ParseEnd function.
+ * @noreturn
+ * @error Invalid or corrupt Handle.
+ */
+native SMC_SetParseEnd(Handle:smc, SMC_ParseEnd:func);
+
+/**
+ * Called when the parser is entering a new section or sub-section.
+ * @note Enclosing quotes are always stripped.
+ *
+ * @param smc The SMC Parse Handle.
+ * @param name String containing section name.
+ * @param opt_quotes True if the section name was quote-enclosed in the file.
+ * @return An SMCResult action to take.
+ */
+functag public SMCResult:SMC_NewSection(Handle:smc, const String:name[], bool:opt_quotes);
+
+/**
+ * Called when the parser finds a new key/value pair.
+ * @note Enclosing quotes are always stripped.
+ *
+ * @param smc The SMC Parse Handle.
+ * @param key String containing key name.
+ * @param value String containing value name.
+ * @param key_quotes Whether or not the key was enclosed in quotes.
+ * @param value_quotes Whether or not the value was enclosed in quotes.
+ * @return An SMCResult action to take.
+ */
+functag public SMCResult:SMC_KeyValue(Handle:smc, const String:key[], const String:value[], bool:key_quotes, bool:value_quotes);
+
+/**
+ * Called when the parser finds the end of the current section.
+ *
+ * @param smc The SMC Parse Handle.
+ * @return An SMCResult action to take.
+ */
+functag public SMCResult:SMC_EndSection(Handle:smc);
+
+/**
+ * Sets the three main reader functions.
+ *
+ * @param smc An SMC parse Handle.
+ * @param ns An SMC_NewSection function pointer.
+ * @param kv An SMC_KeyValue function pointer.
+ * @param es An SMC_EndSection function pointer.
+ * @noreturn
+ */
+native SMC_SetReaders(Handle:smc, SMC_NewSection:ns, SMC_KeyValue:kv, SMC_EndSection:es);
+
+/**
+ * Called whenever a raw line is read.
+ *
+ * @param smc The SMC Parse Handle.
+ * @param line A string containing the raw line from the file.
+ * @param lineno The line number it occurs on.
+ * @return An SMCResult action to take.
+ */
+functag public SMCResult:SMC_RawLine(Handle:smc, const String:line[], lineno);
+
+/**
+ * Sets a raw line reader on an SMC parser Handle.
+ *
+ * @param smc Handle to an SMC Parse.
+ * @param func SMC_RawLine function.
+ * @noreturn
+ */
+native SMC_SetRawLine(Handle:smc, SMC_RawLine:func);
diff --git a/sourcemod-1.5-dev/scripting/include/tf2.inc b/sourcemod-1.5-dev/scripting/include/tf2.inc
new file mode 100644
index 0000000..789463d
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/tf2.inc
@@ -0,0 +1,440 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _tf2_included
+ #endinput
+#endif
+#define _tf2_included
+
+#define TF_STUNFLAG_SLOWDOWN (1 << 0) /**< activates slowdown modifier */
+#define TF_STUNFLAG_BONKSTUCK (1 << 1) /**< bonk sound, stuck */
+#define TF_STUNFLAG_LIMITMOVEMENT (1 << 2) /**< disable forward/backward movement */
+#define TF_STUNFLAG_CHEERSOUND (1 << 3) /**< cheering sound */
+#define TF_STUNFLAG_NOSOUNDOREFFECT (1 << 5) /**< no sound or particle */
+#define TF_STUNFLAG_THIRDPERSON (1 << 6) /**< panic animation */
+#define TF_STUNFLAG_GHOSTEFFECT (1 << 7) /**< ghost particles */
+
+#define TF_STUNFLAGS_LOSERSTATE TF_STUNFLAG_SLOWDOWN|TF_STUNFLAG_NOSOUNDOREFFECT|TF_STUNFLAG_THIRDPERSON
+#define TF_STUNFLAGS_GHOSTSCARE TF_STUNFLAG_GHOSTEFFECT|TF_STUNFLAG_THIRDPERSON
+#define TF_STUNFLAGS_SMALLBONK TF_STUNFLAG_THIRDPERSON|TF_STUNFLAG_SLOWDOWN
+#define TF_STUNFLAGS_NORMALBONK TF_STUNFLAG_BONKSTUCK
+#define TF_STUNFLAGS_BIGBONK TF_STUNFLAG_CHEERSOUND|TF_STUNFLAG_BONKSTUCK
+
+enum TFClassType
+{
+ TFClass_Unknown = 0,
+ TFClass_Scout,
+ TFClass_Sniper,
+ TFClass_Soldier,
+ TFClass_DemoMan,
+ TFClass_Medic,
+ TFClass_Heavy,
+ TFClass_Pyro,
+ TFClass_Spy,
+ TFClass_Engineer
+};
+
+enum TFTeam
+{
+ TFTeam_Unassigned = 0,
+ TFTeam_Spectator = 1,
+ TFTeam_Red = 2,
+ TFTeam_Blue = 3
+};
+
+enum TFCond
+{
+ TFCond_Slowed = 0,
+ TFCond_Zoomed,
+ TFCond_Disguising,
+ TFCond_Disguised,
+ TFCond_Cloaked,
+ TFCond_Ubercharged,
+ TFCond_TeleportedGlow,
+ TFCond_Taunting,
+ TFCond_UberchargeFading,
+ TFCond_Unknown1, //9
+ TFCond_CloakFlicker = 9,
+ TFCond_Teleporting,
+ TFCond_Kritzkrieged,
+ TFCond_Unknown2, //12
+ TFCond_TmpDamageBonus = 12,
+ TFCond_DeadRingered,
+ TFCond_Bonked,
+ TFCond_Dazed,
+ TFCond_Buffed,
+ TFCond_Charging,
+ TFCond_DemoBuff,
+ TFCond_CritCola,
+ TFCond_InHealRadius,
+ TFCond_Healing,
+ TFCond_OnFire,
+ TFCond_Overhealed,
+ TFCond_Jarated,
+ TFCond_Bleeding,
+ TFCond_DefenseBuffed,
+ TFCond_Milked,
+ TFCond_MegaHeal,
+ TFCond_RegenBuffed,
+ TFCond_MarkedForDeath,
+ TFCond_NoHealingDamageBuff,
+ TFCond_SpeedBuffAlly, //32
+ TFCond_HalloweenCritCandy,
+ TFCond_CritCanteen,
+ TFCond_CritDemoCharge,
+ TFCond_CritHype,
+ TFCond_CritOnFirstBlood,
+ TFCond_CritOnWin,
+ TFCond_CritOnFlagCapture,
+ TFCond_CritOnKill,
+ TFCond_RestrictToMelee,
+ TFCond_DefenseBuffNoCritBlock,
+ TFCond_Reprogrammed,
+ TFCond_CritMmmph,
+ TFCond_DefenseBuffMmmph,
+ TFCond_FocusBuff,
+ TFCond_DisguiseRemoved,
+ TFCond_MarkedForDeathSilent,
+ TFCond_DisguisedAsDispenser,
+ TFCond_Sapped,
+ TFCond_UberchargedHidden,
+ TFCond_UberchargedCanteen,
+ TFCond_HalloweenBombHead,
+ TFCond_HalloweenThriller,
+ TFCond_RadiusHealOnDamage,
+ TFCond_CritOnDamage,
+ TFCond_UberchargedOnTakeDamage,
+ TFCond_UberBulletResist,
+ TFCond_UberBlastResist,
+ TFCond_UberFireResist,
+ TFCond_SmallBulletResist,
+ TFCond_SmallBlastResist,
+ TFCond_SmallFireResist,
+ TFCond_Stealthed, // 64
+ TFCond_MedigunDebuff,
+ TFCond_StealthedUserBuffFade,
+ TFCond_BulletImmune,
+ TFCond_BlastImmune,
+ TFCond_FireImmune,
+ TFCond_PreventDeath,
+ TFCond_MVMBotRadiowave,
+ TFCond_HalloweenSpeedBoost,
+ TFCond_HalloweenQuickHeal,
+ TFCond_HalloweenGiant,
+ TFCond_HalloweenTiny,
+ TFCond_HalloweenInHell,
+ TFCond_HalloweenGhostMode,
+};
+
+const Float:TFCondDuration_Infinite = -1.0;
+
+enum TFHoliday
+{
+ TFHoliday_Birthday = 1,
+ TFHoliday_Halloween,
+ TFHoliday_Christmas,
+ TFHoliday_ValentinesDay,
+ TFHoliday_MeetThePyro,
+ TFHoliday_FullMoon,
+ TFHoliday_HalloweenOrFullMoon,
+ TFHoliday_HalloweenOrFullMoonOrValentines,
+ TFHoliday_AprilFools,
+};
+
+enum TFObjectType
+{
+ TFObject_CartDispenser = 0,
+ TFObject_Dispenser = 0,
+ TFObject_Teleporter = 1,
+ TFObject_Sentry = 2,
+ TFObject_Sapper = 3
+};
+
+enum TFObjectMode
+{
+ TFObjectMode_None = 0,
+ TFObjectMode_Entrance = 0,
+ TFObjectMode_Exit = 1
+};
+
+/**
+ * Sets a client on fire for 10 seconds.
+ *
+ * @param client Player's index.
+ * @param attacker Attacker's index.
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native TF2_IgnitePlayer(client, attacker);
+
+/**
+ * Respawns a client
+ *
+ * @param client Player's index.
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native TF2_RespawnPlayer(client);
+
+/**
+ * Regenerates a client's health and ammunition
+ *
+ * @param client Player's index.
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native TF2_RegeneratePlayer(client);
+
+/**
+ * Adds a condition to a player
+ *
+ * @param client Player's index.
+ * @param condition Integer identifier of condition to apply.
+ * @param duration Duration of condition (does not apply to all conditions).
+ * Pass TFCondDuration_Infinite to apply until manually removed.
+ * @param inflictor Condition inflictor's index (0 for no inflictor).
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native TF2_AddCondition(client, TFCond:condition, Float:duration=TFCondDuration_Infinite, inflictor=0);
+
+/**
+ * Removes a condition from a player
+ *
+ * @param client Player's index.
+ * @param condition Integer identifier of condition to remove.
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native TF2_RemoveCondition(client, TFCond:condition);
+
+/**
+ * Enables/disables PowerPlay mode on a player.
+ *
+ * @param client Player's index.
+ * @param enabled Whether to enable or disable PowerPlay on player.
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native TF2_SetPlayerPowerPlay(client, bool:enabled);
+
+/**
+ * Disguises a client to the given model and team. Only has an effect on spies.
+ *
+ * Note: This only starts the disguise process and a delay occurs before the spy is fully disguised
+ *
+ * @param client Player's index.
+ * @param team Team to disguise the player as (only TFTeam_Red and TFTeam_Blue have an effect)
+ * @param class TFClassType class to disguise the player as
+ * @param target Specific target player to disguise as (0 for any)
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native TF2_DisguisePlayer(client, TFTeam:team, TFClassType:class, target=0);
+
+/**
+ * Removes the current disguise from a client. Only has an effect on spies.
+ *
+ * @param client Player's index.
+ * @noreturn
+ * @error Invalid client index, client not in game, or no mod support.
+ */
+native TF2_RemovePlayerDisguise(client);
+
+/**
+ * Stuns a client
+ *
+ * @param client Player's index.
+ * @param duration Duration of stun.
+ * @param slowdown Slowdown percent (as decimal, 0.00-1.00)
+ * Ignored if TF_STUNFLAG_SLOWDOWN is not set.
+ * @param stunflags Stun flags.
+ * @param attacker Attacker's index (0 is allowed for world).
+ * @noreturn
+ */
+native TF2_StunPlayer(client, Float:duration, Float:slowdown=0.0, stunflags, attacker=0);
+
+/**
+ * Induces the bleed effect on a client
+ *
+ * @param client Player's index.
+ * @param attacker Attacker's index.
+ * @param duration Duration of bleeding (in seconds).
+ * @noreturn
+ */
+native TF2_MakeBleed(client, attacker, Float:duration);
+
+/**
+ * Retrieves the entity index of the CPlayerResource entity
+ *
+ * @return The current resource entity index.
+ */
+#pragma deprecated Use GetPlayerResourceEntity instead
+native TF2_GetResourceEntity();
+
+/**
+ * Finds the TFClassType for a given class name.
+ *
+ * @param classname A classname string such as "sniper" or "demoman"
+ * @return A TFClassType constant.
+ */
+native TFClassType:TF2_GetClass(const String:classname[]);
+
+/**
+ * Called on weapon fire to decide if the current shot should be critical.
+ * Return Plugin_Continue to let the original calculation or return a higher
+ * action to override the decision with the value of 'result'
+ *
+ * @note Since critical shots are also calculated client side any changes made with
+ * this will not show for the shooter. Projectile weapons such as the rocketlauncher
+ * and demoman weapons will show a critical bullet but no critical sound effect.
+ * Bullet hits should appear as expected.
+ *
+ * @param client Client Index.
+ * @param weapon Weapon entity Index.
+ * @param weaponname Classname of the weapon.
+ * @param result Buffer param for the result of the decision.
+ */
+forward Action:TF2_CalcIsAttackCritical(client, weapon, String:weaponname[], &bool:result);
+
+/**
+ * @deprecated No longer called. Use TF2_OnIsHolidayActive.
+ */
+#pragma deprecated No longer called. Use TF2_OnIsHolidayActive.
+forward Action:TF2_OnGetHoliday(&TFHoliday:holiday);
+
+/**
+ * Called at various times when the game checks to see if the given holiday is active.
+ * Return Plugin_Continue to let the original calculation or return a higher
+ * action to override the decision with the value of 'result'
+ *
+ * @param holiday Holiday being checked.
+ * @param result Buffer param for the result of the decision.
+ * @return Plugin_Continue for original calculation, higher value to use 'result'.
+ */
+forward Action:TF2_OnIsHolidayActive(TFHoliday:holiday, &bool:result);
+
+/**
+ * Returns whether or not a holiday is active
+ *
+ * @param holiday Holiday being checked.
+ * @return Boolean of whether or not the holiday is active.
+ */
+native bool:TF2_IsHolidayActive(TFHoliday:holiday);
+
+/**
+ * Returns whether or not a client (Player) is in a duel.
+ *
+ * @param client Client Index.
+ * @return Boolean of whether or not the client/player is dueling.
+ */
+native bool:TF2_IsPlayerInDuel(client);
+
+/**
+ * Called after a condition is added to a player
+ *
+ * @param client Index of the client to which the conditon is being added.
+ * @param condition Condition that is being added.
+ * @noreturn
+ */
+forward TF2_OnConditionAdded(client, TFCond:condition);
+
+/**
+ * Called after a condition is removed from a player
+ *
+ * @param client Index of the client to which the condition is being removed.
+ * @param condition Condition that is being removed.
+ * @noreturn
+ */
+forward TF2_OnConditionRemoved(client, TFCond:condition);
+
+/**
+ * Called when the server enters the Waiting for Players round state
+ *
+ * @noreturn
+ */
+forward TF2_OnWaitingForPlayersStart();
+
+/**
+ * Called when the server exits the Waiting for Players round state
+ *
+ * @noreturn
+ */
+forward TF2_OnWaitingForPlayersEnd();
+
+/**
+ * Called when a player attempts to use a teleporter to decide if the player should be allowed to teleport.
+ * Return Plugin_Continue to let the original calculation or return a higher
+ * action to override the decision with the value of 'result'
+ *
+ * @param client Client index.
+ * @param teleporter Teleporter entity index.
+ * @param result Buffer param for the result of the decision.
+ * This is prepopulated with the game's original decision to let a player teleport.
+ * @return Plugin_Continue for original calculation, higher value to use 'result'.
+ */
+forward Action:TF2_OnPlayerTeleport(client, teleporter, &bool:result);
+
+/**
+ * Do not edit below this line!
+ */
+public Extension:__ext_tf2 =
+{
+ name = "TF2 Tools",
+ file = "game.tf2.ext",
+ autoload = 0,
+#if defined REQUIRE_EXTENSIONS
+ required = 1,
+#else
+ required = 0,
+#endif
+};
+
+#if !defined REQUIRE_EXTENSIONS
+public __ext_tf2_SetNTVOptional()
+{
+ MarkNativeAsOptional("TF2_IgnitePlayer");
+ MarkNativeAsOptional("TF2_RespawnPlayer");
+ MarkNativeAsOptional("TF2_RegeneratePlayer");
+ MarkNativeAsOptional("TF2_AddCondition");
+ MarkNativeAsOptional("TF2_RemoveCondition");
+ MarkNativeAsOptional("TF2_SetPlayerPowerPlay");
+ MarkNativeAsOptional("TF2_DisguisePlayer");
+ MarkNativeAsOptional("TF2_RemovePlayerDisguise");
+ MarkNativeAsOptional("TF2_StunPlayer");
+ MarkNativeAsOptional("TF2_MakeBleed");
+ MarkNativeAsOptional("TF2_GetResourceEntity");
+ MarkNativeAsOptional("TF2_GetClass");
+ MarkNativeAsOptional("TF2_IsPlayerInDuel");
+ MarkNativeAsOptional("TF2_IsHolidayActive");
+}
+#endif
diff --git a/sourcemod-1.5-dev/scripting/include/tf2_stocks.inc b/sourcemod-1.5-dev/scripting/include/tf2_stocks.inc
new file mode 100644
index 0000000..10fff4b
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/tf2_stocks.inc
@@ -0,0 +1,548 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _tf2_stocks_included
+ #endinput
+#endif
+#define _tf2_stocks_included
+
+#include <tf2>
+#include <sdktools>
+
+#define TF_CONDFLAG_NONE 0
+#define TF_CONDFLAG_SLOWED (1 << 0)
+#define TF_CONDFLAG_ZOOMED (1 << 1)
+#define TF_CONDFLAG_DISGUISING (1 << 2)
+#define TF_CONDFLAG_DISGUISED (1 << 3)
+#define TF_CONDFLAG_CLOAKED (1 << 4)
+#define TF_CONDFLAG_UBERCHARGED (1 << 5)
+#define TF_CONDFLAG_TELEPORTGLOW (1 << 6)
+#define TF_CONDFLAG_TAUNTING (1 << 7)
+#define TF_CONDFLAG_UBERCHARGEFADE (1 << 8)
+#define TF_CONDFLAG_CLOAKFLICKER (1 << 9)
+#define TF_CONDFLAG_TELEPORTING (1 << 10)
+#define TF_CONDFLAG_KRITZKRIEGED (1 << 11)
+#define TF_CONDFLAG_DEADRINGERED (1 << 13)
+#define TF_CONDFLAG_BONKED (1 << 14)
+#define TF_CONDFLAG_DAZED (1 << 15)
+#define TF_CONDFLAG_BUFFED (1 << 16)
+#define TF_CONDFLAG_CHARGING (1 << 17)
+#define TF_CONDFLAG_DEMOBUFF (1 << 18)
+#define TF_CONDFLAG_CRITCOLA (1 << 19)
+#define TF_CONDFLAG_INHEALRADIUS (1 << 20)
+#define TF_CONDFLAG_HEALING (1 << 21)
+#define TF_CONDFLAG_ONFIRE (1 << 22)
+#define TF_CONDFLAG_OVERHEALED (1 << 23)
+#define TF_CONDFLAG_JARATED (1 << 24)
+#define TF_CONDFLAG_BLEEDING (1 << 25)
+#define TF_CONDFLAG_DEFENSEBUFFED (1 << 26)
+#define TF_CONDFLAG_MILKED (1 << 27)
+#define TF_CONDFLAG_MEGAHEAL (1 << 28)
+#define TF_CONDFLAG_REGENBUFFED (1 << 29)
+#define TF_CONDFLAG_MARKEDFORDEATH (1 << 30)
+
+#define TF_DEATHFLAG_KILLERDOMINATION (1 << 0)
+#define TF_DEATHFLAG_ASSISTERDOMINATION (1 << 1)
+#define TF_DEATHFLAG_KILLERREVENGE (1 << 2)
+#define TF_DEATHFLAG_ASSISTERREVENGE (1 << 3)
+#define TF_DEATHFLAG_FIRSTBLOOD (1 << 4)
+#define TF_DEATHFLAG_DEADRINGER (1 << 5)
+#define TF_DEATHFLAG_INTERRUPTED (1 << 6)
+#define TF_DEATHFLAG_GIBBED (1 << 7)
+#define TF_DEATHFLAG_PURGATORY (1 << 8)
+
+// Custom kill identifiers for the customkill property on the player_death event
+enum {
+ TF_CUSTOM_HEADSHOT = 1,
+ TF_CUSTOM_BACKSTAB,
+ TF_CUSTOM_BURNING,
+ TF_CUSTOM_WRENCH_FIX,
+ TF_CUSTOM_MINIGUN,
+ TF_CUSTOM_SUICIDE,
+ TF_CUSTOM_TAUNT_HADOUKEN,
+ TF_CUSTOM_BURNING_FLARE,
+ TF_CUSTOM_TAUNT_HIGH_NOON,
+ TF_CUSTOM_TAUNT_GRAND_SLAM,
+ TF_CUSTOM_PENETRATE_MY_TEAM,
+ TF_CUSTOM_PENETRATE_ALL_PLAYERS,
+ TF_CUSTOM_TAUNT_FENCING,
+ TF_CUSTOM_PENETRATE_HEADSHOT,
+ TF_CUSTOM_TAUNT_ARROW_STAB,
+ TF_CUSTOM_TELEFRAG,
+ TF_CUSTOM_BURNING_ARROW,
+ TF_CUSTOM_FLYINGBURN,
+ TF_CUSTOM_PUMPKIN_BOMB,
+ TF_CUSTOM_DECAPITATION,
+ TF_CUSTOM_TAUNT_GRENADE,
+ TF_CUSTOM_BASEBALL,
+ TF_CUSTOM_CHARGE_IMPACT,
+ TF_CUSTOM_TAUNT_BARBARIAN_SWING,
+ TF_CUSTOM_AIR_STICKY_BURST,
+ TF_CUSTOM_DEFENSIVE_STICKY,
+ TF_CUSTOM_PICKAXE,
+ TF_CUSTOM_ROCKET_DIRECTHIT,
+ TF_CUSTOM_TAUNT_UBERSLICE,
+ TF_CUSTOM_PLAYER_SENTRY,
+ TF_CUSTOM_STANDARD_STICKY,
+ TF_CUSTOM_SHOTGUN_REVENGE_CRIT,
+ TF_CUSTOM_TAUNT_ENGINEER_SMASH,
+ TF_CUSTOM_BLEEDING,
+ TF_CUSTOM_GOLD_WRENCH,
+ TF_CUSTOM_CARRIED_BUILDING,
+ TF_CUSTOM_COMBO_PUNCH,
+ TF_CUSTOM_TAUNT_ENGINEER_ARM,
+ TF_CUSTOM_FISH_KILL,
+ TF_CUSTOM_TRIGGER_HURT,
+ TF_CUSTOM_DECAPITATION_BOSS,
+ TF_CUSTOM_STICKBOMB_EXPLOSION,
+ TF_CUSTOM_AEGIS_ROUND,
+ TF_CUSTOM_FLARE_EXPLOSION,
+ TF_CUSTOM_BOOTS_STOMP,
+ TF_CUSTOM_PLASMA,
+ TF_CUSTOM_PLASMA_CHARGED,
+ TF_CUSTOM_PLASMA_GIB,
+ TF_CUSTOM_PRACTICE_STICKY,
+ TF_CUSTOM_EYEBALL_ROCKET,
+ TF_CUSTOM_HEADSHOT_DECAPITATION,
+ TF_CUSTOM_TAUNT_ARMAGEDDON,
+ TF_CUSTOM_FLARE_PELLET,
+ TF_CUSTOM_CLEAVER,
+ TF_CUSTOM_CLEAVER_CRIT,
+ TF_CUSTOM_SAPPER_RECORDER_DEATH,
+ TF_CUSTOM_MERASMUS_PLAYER_BOMB,
+ TF_CUSTOM_MERASMUS_GRENADE,
+ TF_CUSTOM_MERASMUS_ZAP,
+ TF_CUSTOM_MERASMUS_DECAPITATION,
+ TF_CUSTOM_CANNONBALL_PUSH,
+ TF_CUSTOM_TAUNT_ALLCLASS_GUITAR_RIFF,
+};
+
+// Weapon codes as used in some events, such as player_death
+// (not to be confused with Item Definition Indexes)
+enum {
+ TF_WEAPON_NONE = 0,
+ TF_WEAPON_BAT,
+ TF_WEAPON_BAT_WOOD,
+ TF_WEAPON_BOTTLE,
+ TF_WEAPON_FIREAXE,
+ TF_WEAPON_CLUB,
+ TF_WEAPON_CROWBAR,
+ TF_WEAPON_KNIFE,
+ TF_WEAPON_FISTS,
+ TF_WEAPON_SHOVEL,
+ TF_WEAPON_WRENCH,
+ TF_WEAPON_BONESAW,
+ TF_WEAPON_SHOTGUN_PRIMARY,
+ TF_WEAPON_SHOTGUN_SOLDIER,
+ TF_WEAPON_SHOTGUN_HWG,
+ TF_WEAPON_SHOTGUN_PYRO,
+ TF_WEAPON_SCATTERGUN,
+ TF_WEAPON_SNIPERRIFLE,
+ TF_WEAPON_MINIGUN,
+ TF_WEAPON_SMG,
+ TF_WEAPON_SYRINGEGUN_MEDIC,
+ TF_WEAPON_TRANQ,
+ TF_WEAPON_ROCKETLAUNCHER,
+ TF_WEAPON_GRENADELAUNCHER,
+ TF_WEAPON_PIPEBOMBLAUNCHER,
+ TF_WEAPON_FLAMETHROWER,
+ TF_WEAPON_GRENADE_NORMAL,
+ TF_WEAPON_GRENADE_CONCUSSION,
+ TF_WEAPON_GRENADE_NAIL,
+ TF_WEAPON_GRENADE_MIRV,
+ TF_WEAPON_GRENADE_MIRV_DEMOMAN,
+ TF_WEAPON_GRENADE_NAPALM,
+ TF_WEAPON_GRENADE_GAS,
+ TF_WEAPON_GRENADE_EMP,
+ TF_WEAPON_GRENADE_CALTROP,
+ TF_WEAPON_GRENADE_PIPEBOMB,
+ TF_WEAPON_GRENADE_SMOKE_BOMB,
+ TF_WEAPON_GRENADE_HEAL,
+ TF_WEAPON_GRENADE_STUNBALL,
+ TF_WEAPON_GRENADE_JAR,
+ TF_WEAPON_GRENADE_JAR_MILK,
+ TF_WEAPON_PISTOL,
+ TF_WEAPON_PISTOL_SCOUT,
+ TF_WEAPON_REVOLVER,
+ TF_WEAPON_NAILGUN,
+ TF_WEAPON_PDA,
+ TF_WEAPON_PDA_ENGINEER_BUILD,
+ TF_WEAPON_PDA_ENGINEER_DESTROY,
+ TF_WEAPON_PDA_SPY,
+ TF_WEAPON_BUILDER,
+ TF_WEAPON_MEDIGUN,
+ TF_WEAPON_GRENADE_MIRVBOMB,
+ TF_WEAPON_FLAMETHROWER_ROCKET,
+ TF_WEAPON_GRENADE_DEMOMAN,
+ TF_WEAPON_SENTRY_BULLET,
+ TF_WEAPON_SENTRY_ROCKET,
+ TF_WEAPON_DISPENSER,
+ TF_WEAPON_INVIS,
+ TF_WEAPON_FLAREGUN,
+ TF_WEAPON_LUNCHBOX,
+ TF_WEAPON_JAR,
+ TF_WEAPON_COMPOUND_BOW,
+ TF_WEAPON_BUFF_ITEM,
+ TF_WEAPON_PUMPKIN_BOMB,
+ TF_WEAPON_SWORD,
+ TF_WEAPON_DIRECTHIT,
+ TF_WEAPON_LIFELINE,
+ TF_WEAPON_LASER_POINTER,
+ TF_WEAPON_DISPENSER_GUN,
+ TF_WEAPON_SENTRY_REVENGE,
+ TF_WEAPON_JAR_MILK,
+ TF_WEAPON_HANDGUN_SCOUT_PRIMARY,
+ TF_WEAPON_BAT_FISH,
+ TF_WEAPON_CROSSBOW,
+ TF_WEAPON_STICKBOMB,
+ TF_WEAPON_HANDGUN_SCOUT_SEC,
+ TF_WEAPON_SODA_POPPER,
+ TF_WEAPON_SNIPERRIFLE_DECAP,
+ TF_WEAPON_RAYGUN,
+ TF_WEAPON_PARTICLE_CANNON,
+ TF_WEAPON_MECHANICAL_ARM,
+ TF_WEAPON_DRG_POMSON,
+ TF_WEAPON_BAT_GIFTWRAP,
+ TF_WEAPON_GRENADE_ORNAMENT,
+ TF_WEAPON_RAYGUN_REVENGE,
+ TF_WEAPON_PEP_BRAWLER_BLASTER,
+ TF_WEAPON_CLEAVER,
+ TF_WEAPON_GRENADE_CLEAVER,
+ TF_WEAPON_STICKY_BALL_LAUNCHER,
+ TF_WEAPON_GRENADE_STICKY_BALL,
+ TF_WEAPON_SHOTGUN_BUILDING_RESCUE,
+ TF_WEAPON_CANNON,
+ TF_WEAPON_THROWABLE,
+ TF_WEAPON_GRENADE_THROWABLE,
+ TF_WEAPON_PDA_SPY_BUILD,
+ TF_WEAPON_GRENADE_WATERBALLOON,
+ TF_WEAPON_HARVESTER_SAW,
+ TF_WEAPON_SPELLBOOK,
+ TF_WEAPON_SPELLBOOK_PROJECTILE,
+ TF_WEAPON_SNIPERRIFLE_CLASSIC,
+};
+
+// TF2 Weapon Loadout Slots
+enum
+{
+ TFWeaponSlot_Primary,
+ TFWeaponSlot_Secondary,
+ TFWeaponSlot_Melee,
+ TFWeaponSlot_Grenade,
+ TFWeaponSlot_Building,
+ TFWeaponSlot_PDA,
+ TFWeaponSlot_Item1,
+ TFWeaponSlot_Item2
+};
+
+// Identifiers for the eventtype property on the teamplay_flag_event event
+enum {
+ TF_FLAGEVENT_PICKEDUP = 1,
+ TF_FLAGEVENT_CAPTURED,
+ TF_FLAGEVENT_DEFENDED,
+ TF_FLAGEVENT_DROPPED,
+ TF_FLAGEVENT_RETURNED
+};
+
+enum TFResourceType
+{
+ TFResource_Ping,
+ TFResource_Score,
+ TFResource_Deaths,
+ TFResource_TotalScore,
+ TFResource_Captures,
+ TFResource_Defenses,
+ TFResource_Dominations,
+ TFResource_Revenge,
+ TFResource_BuildingsDestroyed,
+ TFResource_Headshots,
+ TFResource_Backstabs,
+ TFResource_HealPoints,
+ TFResource_Invulns,
+ TFResource_Teleports,
+ TFResource_ResupplyPoints,
+ TFResource_KillAssists,
+ TFResource_MaxHealth,
+ TFResource_PlayerClass
+};
+
+static const String:TFResourceNames[TFResourceType][] =
+{
+ "m_iPing",
+ "m_iScore",
+ "m_iDeaths",
+ "m_iTotalScore",
+ "m_iCaptures",
+ "m_iDefenses",
+ "m_iDominations",
+ "m_iRevenge",
+ "m_iBuildingsDestroyed",
+ "m_iHeadshots",
+ "m_iBackstabs",
+ "m_iHealPoints",
+ "m_iInvulns",
+ "m_iTeleports",
+ "m_iResupplyPoints",
+ "m_iKillAssists",
+ "m_iMaxHealth",
+ "m_iPlayerClass"
+};
+
+/**
+ * Get's a Clients current class.
+ *
+ * @param client Player's index.
+ * @return Current TFClassType of player.
+ * @error Invalid client index.
+ */
+stock TFClassType:TF2_GetPlayerClass(client)
+{
+ return TFClassType:GetEntProp(client, Prop_Send, "m_iClass");
+}
+
+/**
+ * Set's a Clients class.
+ *
+ * Note: If setting player class in a player spawn hook weapons should be set to false.
+ *
+ * @param client Player's index.
+ * @param class TFClassType class symbol.
+ * @param weapons This paramater is ignored.
+ * @param persistent If true changes the players desired class so the change stays after death.
+ * @noreturn
+ * @error Invalid client index.
+ */
+stock TF2_SetPlayerClass(client, TFClassType:class, bool:weapons=true, bool:persistent=true)
+{
+ SetEntProp(client, Prop_Send, "m_iClass", _:class);
+
+ if (persistent)
+ {
+ SetEntProp(client, Prop_Send, "m_iDesiredPlayerClass", _:class);
+ }
+}
+
+/**
+ * Retrieves client data from the resource entity
+ *
+ * @param client Player's index.
+ * @param type ResourceType constant
+ * @return Value or -1 on failure.
+ * @error Invalid client index, client not in game or failed to find resource entity.
+ */
+#pragma deprecated Use GetPlayerResourceEntity and GetEntProp instead
+stock TF2_GetPlayerResourceData(client, TFResourceType:type)
+{
+ if (!IsClientConnected(client))
+ {
+ return -1;
+ }
+
+ new offset = FindSendPropInfo("CTFPlayerResource", TFResourceNames[type]);
+
+ if (offset < 1)
+ {
+ return -1;
+ }
+
+ new entity = TF2_GetResourceEntity();
+
+ if (entity == -1)
+ {
+ return -1;
+ }
+
+ return GetEntData(entity, offset + (client*4));
+}
+
+/**
+ * Sets client data in the resource entity
+ *
+ * Note: The game overwrites these values every frame, so changing them will have very little effect.
+ *
+ * @param client Player's index.
+ * @param type ResourceType constant
+ * @param value Value to set.
+ * @return Value or -1 on failure.
+ * @error Invalid client index, client not in game or failed to find resource entity.
+ */
+#pragma deprecated Use GetPlayerResourceEntity and SetEntProp instead
+stock bool:TF2_SetPlayerResourceData(client, TFResourceType:type, any:value)
+{
+ if (!IsClientConnected(client))
+ {
+ return false;
+ }
+
+ new offset = FindSendPropInfo("CTFPlayerResource", TFResourceNames[type]);
+
+ if (offset < 1)
+ {
+ return false;
+ }
+
+ new entity = TF2_GetResourceEntity();
+
+ if (entity == -1)
+ {
+ return false;
+ }
+
+ SetEntData(entity, offset + (client*4), value);
+
+ return true;
+}
+
+/**
+ * Removes all weapons from a client's weapon slot
+ *
+ * @param client Player's index.
+ * @param slot Slot index (0-5)
+ * @noreturn
+ * @error Invalid client, invalid slot or lack of mod support
+ */
+stock TF2_RemoveWeaponSlot(client, slot)
+{
+ new weaponIndex;
+ while ((weaponIndex = GetPlayerWeaponSlot(client, slot)) != -1)
+ {
+ RemovePlayerItem(client, weaponIndex);
+ AcceptEntityInput(weaponIndex, "Kill");
+ }
+}
+
+/**
+ * Removes all weapons from a client
+ *
+ * @param client Player's index.
+ * @noreturn
+ */
+stock TF2_RemoveAllWeapons(client)
+{
+ for (new i = 0; i <= 5; i++)
+ {
+ TF2_RemoveWeaponSlot(client, i);
+ }
+}
+
+/**
+ * Gets a player's condition bits
+ *
+ * @param client Player's index.
+ * @return Player's condition bits
+ */
+#pragma deprecated Use TF2_IsPlayerInCondition instead.
+stock TF2_GetPlayerConditionFlags(client)
+{
+ return GetEntProp(client, Prop_Send, "m_nPlayerCond")|GetEntProp(client, Prop_Send, "_condition_bits");
+}
+
+/**
+ * Check whether or not a condition is set on a player
+ *
+ * @param client Player's index.
+ * @param cond TFCond constant
+ * @return True if set, false otherwise
+ */
+stock bool:TF2_IsPlayerInCondition(client, TFCond:cond)
+{
+ // Conditions are stored across two netprops now, one for each 32-bit segment.
+ if (_:cond < 32)
+ {
+ new bit = 1 << _:cond;
+ if ((GetEntProp(client, Prop_Send, "m_nPlayerCond") & bit) == bit)
+ {
+ return true;
+ }
+
+ if ((GetEntProp(client, Prop_Send, "_condition_bits") & bit) == bit)
+ {
+ return true;
+ }
+ }
+ else if (_:cond < 64)
+ {
+ new bit = (1 << (_:cond - 32));
+ if ((GetEntProp(client, Prop_Send, "m_nPlayerCondEx") & bit) == bit)
+ {
+ return true;
+ }
+ }
+ else
+ {
+ new bit = (1 << (_:cond - 64));
+ if ((GetEntProp(client, Prop_Send, "m_nPlayerCondEx2") & bit) == bit)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Gets an entity's object type.
+ *
+ * @param entity Entity index.
+ * @return Current TFObjectType of entity.
+ * @error Invalid entity index.
+ */
+stock TFObjectType:TF2_GetObjectType(entity)
+{
+ new offset = GetEntSendPropOffs(entity, "m_iObjectType");
+
+ if (offset <= 0)
+ {
+ ThrowError("Entity index %d is not an object", entity);
+ }
+
+ return TFObjectType:GetEntData(entity, offset);
+}
+
+/**
+ * Gets an entity's object mode.
+ *
+ * @param entity Entity index.
+ * @return Current TFObjectMode of entity.
+ * @error Invalid entity index.
+ */
+stock TFObjectMode:TF2_GetObjectMode(entity)
+{
+ new offset = GetEntSendPropOffs(entity, "m_iObjectMode");
+
+ if (offset <= 0)
+ {
+ ThrowError("Entity index %d is not an object", entity);
+ }
+
+ return TFObjectMode:GetEntData(entity, offset);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/timers.inc b/sourcemod-1.5-dev/scripting/include/timers.inc
new file mode 100644
index 0000000..dbaeb14
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/timers.inc
@@ -0,0 +1,211 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _timers_included
+ #endinput
+#endif
+#define _timers_included
+
+#include <datapack>
+
+#define TIMER_REPEAT (1<<0) /**< Timer will repeat until it returns Plugin_Stop */
+#define TIMER_FLAG_NO_MAPCHANGE (1<<1) /**< Timer will not carry over mapchanges */
+#define TIMER_HNDL_CLOSE (1<<9) /**< Deprecated define, replaced by below */
+#define TIMER_DATA_HNDL_CLOSE (1<<9) /**< Timer will automatically call CloseHandle() on its data when finished */
+
+/**
+ * Any of the following prototypes will work for a timed function.
+ */
+funcenum Timer
+{
+ /**
+ * Called when the timer interval has elapsed.
+ *
+ * @param timer Handle to the timer object.
+ * @param hndl Handle passed to CreateTimer() when timer was created.
+ * @return Plugin_Stop to stop a repeating timer, any other value for
+ * default behavior.
+ */
+ Action:public(Handle:timer, Handle:hndl),
+
+ /**
+ * Called when the timer interval has elapsed.
+ *
+ * @param timer Handle to the timer object.
+ * @param data Data passed to CreateTimer() when timer was created.
+ * @return Plugin_Stop to stop a repeating timer, any other value for
+ * default behavior.
+ */
+ Action:public(Handle:timer, any:data),
+
+ /**
+ * Called when the timer interval has elapsed.
+ *
+ * @param timer Handle to the timer object.
+ * @return Plugin_Stop to stop a repeating timer, any other value for
+ * default behavior.
+ */
+ Action:public(Handle:timer),
+};
+
+/**
+ * Creates a basic timer. Calling CloseHandle() on a timer will end the timer.
+ *
+ * @param interval Interval from the current game time to execute the given function.
+ * @param func Function to execute once the given interval has elapsed.
+ * @param data Handle or value to pass through to the timer callback function.
+ * @param flags Flags to set (such as repeatability or auto-Handle closing).
+ * @return Handle to the timer object. You do not need to call CloseHandle().
+ * If the timer could not be created, INVALID_HANDLE will be returned.
+ */
+native Handle:CreateTimer(Float:interval, Timer:func, any:data=INVALID_HANDLE, flags=0);
+
+/**
+ * Kills a timer. Use this instead of CloseHandle() if you need more options.
+ *
+ * @param timer Timer Handle to kill.
+ * @param autoClose If autoClose is true, the data that was passed to CreateTimer() will
+ * be closed as a handle if TIMER_DATA_HNDL_CLOSE was not specified.
+ * @noreturn
+ */
+native KillTimer(Handle:timer, bool:autoClose=false);
+
+/**
+ * Manually triggers a timer so its function will be called.
+ *
+ * @param timer Timer Handle to trigger.
+ * @param reset If reset is true, the elapsed time counter is reset
+ * so the full interval must pass again.
+ * @noreturn
+ */
+native TriggerTimer(Handle:timer, bool:reset=false);
+
+/**
+ * Returns the simulated game time.
+ *
+ * This time is internally maintained by SourceMod and is based on the game
+ * tick count and tick rate. Unlike GetGameTime(), it will increment past
+ * map changes and while no players are connected. Unlike GetEngineTime(),
+ * it will not increment based on the system clock (i.e. it is still bound
+ * to the ticking process).
+ *
+ * @return Time based on the game tick count.
+ */
+native Float:GetTickedTime();
+
+/**
+ * Returns an estimate of the time left before the map ends. If the server
+ * has not processed any frames yet (i.e. no players have joined the map yet),
+ * then the time left returned will always be infinite.
+ *
+ * @param timeleft Variable to store the time, in seconds. If the
+ * value is less than 0, the time limit is infinite.
+ * @return True if the operation is supported, false otherwise.
+ */
+native bool:GetMapTimeLeft(&timeleft);
+
+/**
+ * Retrieves the current map time limit. If the server has not processed any
+ * frames yet (i.e. no players have joined the map yet), then the time limit
+ * returned will always be 0.
+ *
+ * @param time Set to the number of total seconds in the map time
+ * limit, or 0 if there is no time limit set.
+ * @return True on success, false if operation is not supported.
+ */
+native bool:GetMapTimeLimit(&time);
+
+/**
+ * Extends the map time limit in a way that will notify all plugins.
+ *
+ * @param time Number of seconds to extend map time limit by.
+ * The number can be negative to decrease the time limit.
+ * If 0, the map will be set to have no time limit.
+ * @return True on success, false if operation is not supported.
+ */
+native bool:ExtendMapTimeLimit(time);
+
+/**
+ * Returns the number of seconds in between game server ticks.
+ *
+ * Note: A tick, in this context, is a frame.
+ *
+ * @return Number of seconds in between ticks.
+ */
+native Float:GetTickInterval();
+
+/**
+ * Notification that the map's time left has changed via a change in the time
+ * limit or a change in the game rules (such as mp_restartgame). This is useful
+ * for plugins trying to create timers based on the time left in the map.
+ *
+ * Calling ExtendMapTimeLimit() from here, without proper precaution, will
+ * cause infinite recursion.
+ *
+ * If the operation is not supported, this will never be called.
+
+ * If the server has not yet processed any frames (i.e. no players have joined
+ * the map yet), then this will be called once the server begins ticking, even
+ * if there is no time limit set.
+ */
+forward OnMapTimeLeftChanged();
+
+/**
+ * Returns whether or not the server is processing frames or not.
+ *
+ * The server does not process frames until at least one client joins the game.
+ * Once the first player has in, even if that player, leaves, the server's
+ * timers and entities will work.
+ *
+ * @return True if the server is ticking, false otherwise.
+ */
+native bool:IsServerProcessing();
+
+/**
+ * Creates a timer associated with a new datapack, and returns the datapack.
+ * @note The datapack is automatically freed when the timer ends.
+ * @note The position of the datapack is not reset or changed for the timer function.
+ *
+ * @param interval Interval from the current game time to execute the given function.
+ * @param func Function to execute once the given interval has elapsed.
+ * @param datapack The newly created datapack is passed though this by-reference
+ * parameter to the timer callback function.
+ * @param flags Timer flags.
+ * @return Handle to the timer object. You do not need to call CloseHandle().
+ */
+stock Handle:CreateDataTimer(Float:interval, Timer:func, &Handle:datapack, flags=0)
+{
+ datapack = CreateDataPack();
+ flags |= TIMER_DATA_HNDL_CLOSE;
+ return CreateTimer(interval, func, datapack, flags);
+}
+
diff --git a/sourcemod-1.5-dev/scripting/include/topmenus.inc b/sourcemod-1.5-dev/scripting/include/topmenus.inc
new file mode 100644
index 0000000..9bc4d7f
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/topmenus.inc
@@ -0,0 +1,314 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _topmenus_included
+ #endinput
+#endif
+#define _topmenus_included
+
+#include <menus>
+
+/**
+ * Actions a top menu will take on an object.
+ */
+enum TopMenuAction
+{
+ /**
+ * An option is being drawn for a menu (or for sorting purposes).
+ *
+ * INPUT : TopMenu Handle, object ID, client index.
+ * OUTPUT: Buffer for rendering, maxlength of buffer.
+ */
+ TopMenuAction_DisplayOption = 0,
+
+ /**
+ * The title of a menu is being drawn for a given object.
+ *
+ * Note: The Object ID will be INVALID_TOPMENUOBJECT if drawing the
+ * root title. Otherwise, the Object ID is a category.
+ *
+ * INPUT : TopMenu Handle, object ID, client index.
+ * OUTPUT: Buffer for rendering, maxlength of buffer.
+ */
+ TopMenuAction_DisplayTitle = 1,
+
+ /**
+ * A menu option has been selected.
+ *
+ * The Object ID will always be an item (not a category).
+ *
+ * INPUT : TopMenu Handle, object ID, client index.
+ */
+ TopMenuAction_SelectOption = 2,
+
+ /**
+ * A menu option is being drawn and its flags can be overridden.
+ *
+ * INPUT : TopMenu Handle, object ID, client index.
+ * OUTPUT: The first byte of the 'buffer' string should be set
+ * to the desired flags. By default, it will contain
+ * ITEMDRAW_DEFAULT.
+ */
+ TopMenuAction_DrawOption = 3,
+
+ /**
+ * Called when an object is being removed from the menu.
+ * This can be used to clean up data stored in the info string.
+ *
+ * INPUT : TopMenu Handle, object ID.
+ */
+ TopMenuAction_RemoveObject = 4,
+};
+
+/**
+ * Top menu object types.
+ */
+enum TopMenuObjectType
+{
+ TopMenuObject_Category = 0, /**< Category (sub-menu branching from root) */
+ TopMenuObject_Item = 1 /**< Item on a sub-menu */
+};
+
+/**
+ * Top menu starting positions for display.
+ */
+enum TopMenuPosition
+{
+ TopMenuPosition_Start = 0, /**< Start/root of the menu */
+ TopMenuPosition_LastRoot = 1, /**< Last position in the root menu */
+ TopMenuPosition_LastCategory = 3, /**< Last position in their last category */
+};
+
+/**
+ * Top menu object tag for type checking.
+ */
+enum TopMenuObject
+{
+ INVALID_TOPMENUOBJECT = 0,
+};
+
+/**
+ * TopMenu callback prototype.
+ *
+ * @param topmenu Handle to the TopMenu.
+ * @param action TopMenuAction being performed.
+ * @param object_id The object ID (if used).
+ * @param param Extra parameter (if used).
+ * @param buffer Output buffer (if used).
+ * @param maxlength Output buffer (if used).
+ * @noreturn
+ */
+functag public TopMenuHandler(Handle:topmenu,
+ TopMenuAction:action,
+ TopMenuObject:object_id,
+ param,
+ String:buffer[],
+ maxlength);
+
+/**
+ * Creates a TopMenu.
+ *
+ * @param handler Handler to use for drawing the root title.
+ * @return A new TopMenu Handle, or INVALID_HANDLE on failure.
+ */
+native Handle:CreateTopMenu(TopMenuHandler:handler);
+
+/**
+ * Re-sorts the items in a TopMenu via a configuration file.
+ *
+ * The format of the configuration file should be a Valve Key-Values
+ * formatted file that SourceMod can parse. There should be one root
+ * section, and one sub-section for each category. Each sub-section's
+ * name should match the category name.
+ *
+ * Each sub-section may only contain key/value pairs in the form of:
+ * key: "item"
+ * value: Name of the item as passed to AddToTopMenu().
+ *
+ * The TopMenu will draw items in the order declared in the configuration
+ * file. If items do not appear in the configuration file, they are sorted
+ * per-player based on how the handler function renders for that player.
+ * These items appear after the configuration sorted items.
+ *
+ * @param topmenu TopMenu Handle.
+ * @param file File path.
+ * @param error Error buffer.
+ * @param maxlength Maximum size of the error buffer.
+ * Error buffer will be filled with a
+ * zero-terminated string if false is
+ * returned.
+ * @return True on success, false on failure.
+ * @error Invalid TopMenu Handle.
+ */
+native bool:LoadTopMenuConfig(Handle:topmenu, const String:file[], String:error[], maxlength);
+
+/**
+ * Adds an object to a TopMenu.
+ *
+ * @param topmenu TopMenu Handle.
+ * @param name Object name (MUST be unique).
+ * @param type Object type.
+ * @param handler Handler for object.
+ * @param parent Parent object ID, or INVALID_TOPMENUOBJECT for none.
+ * Items must have a category parent.
+ * Categories must not have a parent.
+ * @param cmdname Command name (for access overrides).
+ * @param flags Default access flags.
+ * @param info_string Arbitrary storage (max 255 bytes).
+ * @return A new TopMenuObject ID, or INVALID_TOPMENUOBJECT on
+ * failure.
+ * @error Invalid TopMenu Handle.
+ */
+native TopMenuObject:AddToTopMenu(Handle:topmenu,
+ const String:name[],
+ TopMenuObjectType:type,
+ TopMenuHandler:handler,
+ TopMenuObject:parent,
+ const String:cmdname[]="",
+ flags=0,
+ const String:info_string[]="");
+
+/**
+ * Retrieves the info string of a top menu item.
+ *
+ * @param topmenu TopMenu Handle.
+ * @param parent TopMenuObject ID.
+ * @param buffer Buffer to store info string.
+ * @param maxlength Maximum size of info string.
+ * @return Number of bytes written, not including the
+ * null terminator.
+ * @error Invalid TopMenu Handle or TopMenuObject ID.
+ */
+native GetTopMenuInfoString(Handle:topmenu, TopMenuObject:parent, String:buffer[], maxlength);
+
+/**
+ * Retrieves the name string of a top menu item.
+ *
+ * @param topmenu TopMenu Handle.
+ * @param object TopMenuObject ID.
+ * @param buffer Buffer to store info string.
+ * @param maxlength Maximum size of info string.
+ * @return Number of bytes written, not including the
+ * null terminator.
+ * @error Invalid TopMenu Handle or TopMenuObject ID.
+ */
+native GetTopMenuObjName(Handle:topmenu, TopMenuObject:object, String:buffer[], maxlength);
+
+/**
+ * Removes an object from a TopMenu.
+ *
+ * Plugins' objects are automatically removed all TopMenus when the given
+ * plugin unloads or pauses. In the case of unpausing, all items are restored.
+ *
+ * @param topmenu TopMenu Handle.
+ * @param object TopMenuObject ID.
+ * @noreturn
+ * @error Invalid TopMenu Handle.
+ */
+native RemoveFromTopMenu(Handle:topmenu, TopMenuObject:object);
+
+/**
+ * Displays a TopMenu to a client.
+ *
+ * @param topmenu TopMenu Handle.
+ * @param client Client index.
+ * @param position Position to display from.
+ * @return True on success, false on failure.
+ * @error Invalid TopMenu Handle or client not in game.
+ */
+native bool:DisplayTopMenu(Handle:topmenu, client, TopMenuPosition:position);
+
+/**
+ * Displays a TopMenu category to a client.
+ *
+ * @param topmenu TopMenu Handle.
+ * @param category Category object id.
+ * @param client Client index.
+ * @return True on success, false on failure.
+ * @error Invalid TopMenu Handle or client not in game.
+ */
+native bool:DisplayTopMenuCategory(Handle:topmenu, TopMenuObject:category, client);
+
+/**
+ * Finds a category's object ID in a TopMenu.
+ *
+ * @param topmenu TopMenu Handle.
+ * @param name Object's unique name.
+ * @return TopMenuObject ID on success, or
+ * INVALID_TOPMENUOBJECT on failure.
+ * @error Invalid TopMenu Handle.
+ */
+native TopMenuObject:FindTopMenuCategory(Handle:topmenu, const String:name[]);
+
+/**
+ * Change the menu title caching behaviour of the TopMenu. By default the titles are cached to reduce overhead.
+ * If you need dynamic menu titles, which can change everytime the menu is displayed to a user, set this to false.
+ *
+ * @param topmenu TopMenu Handle.
+ * @param cache_titles Cache the menu titles and don't call the handler with TopMenuAction_DisplayTitle everytime the menu is drawn?
+ * @noreturn
+ * @error Invalid TopMenu Handle
+ */
+native SetTopMenuTitleCaching(Handle:topmenu, bool:cache_titles);
+
+/**
+ * Do not edit below this line!
+ */
+public Extension:__ext_topmenus =
+{
+ name = "TopMenus",
+ file = "topmenus.ext",
+#if defined AUTOLOAD_EXTENSIONS
+ autoload = 1,
+#else
+ autoload = 0,
+#endif
+#if defined REQUIRE_EXTENSIONS
+ required = 1,
+#else
+ required = 0,
+#endif
+};
+
+#if !defined REQUIRE_EXTENSIONS
+public __ext_topmenus_SetNTVOptional()
+{
+ MarkNativeAsOptional("CreateTopMenu");
+ MarkNativeAsOptional("LoadTopMenuConfig");
+ MarkNativeAsOptional("AddToTopMenu");
+ MarkNativeAsOptional("RemoveFromTopMenu");
+ MarkNativeAsOptional("DisplayTopMenu");
+ MarkNativeAsOptional("DisplayTopMenuCategory");
+ MarkNativeAsOptional("FindTopMenuCategory");
+ MarkNativeAsOptional("SetTopMenuTitleCaching");
+}
+#endif
diff --git a/sourcemod-1.5-dev/scripting/include/usermessages.inc b/sourcemod-1.5-dev/scripting/include/usermessages.inc
new file mode 100644
index 0000000..5a9538d
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/usermessages.inc
@@ -0,0 +1,218 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _eventsmsgs_included
+ #endinput
+#endif
+#define _eventsmsgs_included
+
+/**
+ * UserMsg helper values.
+ */
+enum UserMsg
+{
+ INVALID_MESSAGE_ID = -1,
+};
+
+/**
+ * UserMsg message serialization formats
+ */
+enum UserMessageType
+{
+ UM_BitBuf = 0,
+ UM_Protobuf,
+};
+
+/**
+ * @section Message Flags.
+ */
+#define USERMSG_RELIABLE (1<<2) /**< Message will be set on the reliable stream */
+#define USERMSG_INITMSG (1<<3) /**< Message will be considered to be an initmsg */
+#define USERMSG_BLOCKHOOKS (1<<7) /**< Prevents the message from triggering SourceMod and Metamod hooks */
+
+/**
+ * @endsection
+ */
+
+/**
+ * Returns usermessage serialization type used for the current engine
+ *
+ * @return The supported usermessage type.
+ */
+native UserMessageType:GetUserMessageType();
+
+/**
+ * Returns the ID of a given message, or -1 on failure.
+ *
+ * @param msg String containing message name (case sensitive).
+ * @return A message index, or INVALID_MESSAGE_ID on failure.
+ */
+native UserMsg:GetUserMessageId(const String:msg[]);
+
+/**
+ * Retrieves the name of a message by ID.
+ *
+ * @param msg_id Message index.
+ * @param msg Buffer to store the name of the message.
+ * @param maxlength Maximum length of string buffer.
+ * @return True if message index is valid, false otherwise.
+ */
+native bool:GetUserMessageName(UserMsg:msg_id, String:msg[], maxlength);
+
+/**
+ * Starts a usermessage (network message).
+ * @note Only one message can be active at a time.
+ * @note It is illegal to send any message while a non-intercept hook is in progress.
+ *
+ * @param msgname Message name to start.
+ * @param clients Array containing player indexes to broadcast to.
+ * @param numClients Number of players in the array.
+ * @param flags Optional flags to set.
+ * @return A handle to a bf_write bit packing structure, or
+ * INVALID_HANDLE on failure.
+ * @error Invalid message name, unable to start a message, invalid client,
+ * or client not connected.
+ */
+native Handle:StartMessage(String:msgname[], clients[], numClients, flags=0);
+
+/**
+ * Starts a usermessage (network message).
+ * @note Only one message can be active at a time.
+ * @note It is illegal to send any message while a non-intercept hook is in progress.
+ *
+ * @param msg Message index to start.
+ * @param clients Array containing player indexes to broadcast to.
+ * @param numClients Number of players in the array.
+ * @param flags Optional flags to set.
+ * @return A handle to a bf_write bit packing structure, or
+ * INVALID_HANDLE on failure.
+ * @error Invalid message name, unable to start a message, invalid client,
+ * or client not connected.
+ */
+native Handle:StartMessageEx(UserMsg:msg, clients[], numClients, flags=0);
+
+/**
+ * Ends a previously started user message (network message).
+ *
+ * @noreturn
+ */
+native EndMessage();
+
+/**
+ * Called when a message is hooked
+ *
+ * @param msg_id Message index.
+ * @param msg Handle to the input bit buffer or protobuf.
+ * @param players Array containing player indexes.
+ * @param playersNum Number of players in the array.
+ * @param reliable True if message is reliable, false otherwise.
+ * @param init True if message is an initmsg, false otherwise.
+ * @return Ignored for normal hooks. For intercept hooks, Plugin_Handled
+ * blocks the message from being sent, and Plugin_Continue
+ * resumes normal functionality.
+ */
+functag public Action:MsgHook(UserMsg:msg_id, Handle:msg, const players[], playersNum, bool:reliable, bool:init);
+
+/**
+ * Called when a message hook has completed.
+ *
+ * @param msg_id Message index.
+ * @param sent True if message was sent, false if blocked.
+ */
+functag public MsgPostHook(UserMsg:msg_id, bool:sent);
+
+/**
+ * Hooks a user message.
+ *
+ * @param msg_id Message index.
+ * @param hook Function to use as a hook.
+ * @param intercept If intercept is true, message will be fully intercepted,
+ * allowing the user to block the message. Otherwise,
+ * the hook is normal and ignores the return value.
+ * @param post Notification function.
+ * @noreturn
+ * @error Invalid message index.
+ */
+native HookUserMessage(UserMsg:msg_id, MsgHook:hook, bool:intercept=false, MsgPostHook:post=MsgPostHook:-1);
+
+/**
+ * Removes one usermessage hook.
+ *
+ * @param msg_id Message index.
+ * @param hook Function used for the hook.
+ * @param intercept Specifies whether the hook was an intercept hook or not.
+ * @noreturn
+ * @error Invalid message index.
+ */
+native UnhookUserMessage(UserMsg:msg_id, MsgHook:hook, bool:intercept=false);
+
+/**
+ * Starts a usermessage (network message) that broadcasts to all clients.
+ * @note See StartMessage or StartMessageEx().
+ *
+ * @param msgname Message name to start.
+ * @param flags Optional flags to set.
+ * @return A handle to a bf_write bit packing structure, or
+ * INVALID_HANDLE on failure.
+ */
+stock Handle:StartMessageAll(String:msgname[], flags=0)
+{
+ new total = 0;
+ new clients[MaxClients];
+ for (new i=1; i<=MaxClients; i++)
+ {
+ if (IsClientConnected(i))
+ {
+ clients[total++] = i;
+ }
+ }
+ return StartMessage(msgname, clients, total, flags);
+}
+
+/**
+ * Starts a simpler usermessage (network message) for one client.
+ * @note See StartMessage or StartMessageEx().
+ *
+ * @param msgname Message name to start.
+ * @param client Client to send to.
+ * @param flags Optional flags to set.
+ * @return A handle to a bf_write bit packing structure, or
+ * INVALID_HANDLE on failure.
+ */
+stock Handle:StartMessageOne(String:msgname[], client, flags=0)
+{
+ new players[1];
+
+ players[0] = client;
+
+ return StartMessage(msgname, players, 1, flags);
+}
diff --git a/sourcemod-1.5-dev/scripting/include/vector.inc b/sourcemod-1.5-dev/scripting/include/vector.inc
new file mode 100644
index 0000000..78ad093
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/vector.inc
@@ -0,0 +1,188 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _vector_included
+ #endinput
+#endif
+#define _vector_included
+
+/**
+ * Calculates a vector's length.
+ *
+ * @param vec Vector.
+ * @param squared If true, the result will be squared (for optimization).
+ * @return Vector length (magnitude).
+ */
+native Float:GetVectorLength(const Float:vec[3], bool:squared=false);
+
+/**
+ * Calculates the distance between two vectors.
+ *
+ * @param vec1 First vector.
+ * @param vec2 Second vector.
+ * @param squared If true, the result will be squared (for optimization).
+ * @return Vector distance.
+ */
+native Float:GetVectorDistance(const Float:vec1[3], const Float:vec2[3], bool:squared=false);
+
+/**
+ * Calculates the dot product of two vectors.
+ *
+ * @param vec1 First vector.
+ * @param vec2 Second vector.
+ * @return Dot product of the two vectors.
+ */
+native Float:GetVectorDotProduct(const Float:vec1[3], const Float:vec2[3]);
+
+/**
+ * Computes the cross product of two vectors. Any input array can be the same
+ * as the output array.
+ *
+ * @param vec1 First vector.
+ * @param vec2 Second vector.
+ * @param result Resultant vector.
+ * @noreturn
+ */
+native GetVectorCrossProduct(const Float:vec1[3], const Float:vec2[3], Float:result[3]);
+
+/**
+ * Normalizes a vector. The input array can be the same as the output array.
+ *
+ * @param vec Vector.
+ * @param result Resultant vector.
+ * @return Vector length.
+ */
+native Float:NormalizeVector(const Float:vec[3], Float:result[3]);
+
+/**
+ * Returns vectors in the direction of an angle.
+ *
+ * @param angle Angle.
+ * @param fwd Forward vector buffer or NULL_VECTOR.
+ * @param right Right vector buffer or NULL_VECTOR.
+ * @param up Up vector buffer or NULL_VECTOR.
+ * @noreturn
+ */
+native GetAngleVectors(const Float:angle[3], Float:fwd[3], Float:right[3], Float:up[3]);
+
+/**
+ * Returns angles from a vector.
+ *
+ * @param vec Vector.
+ * @param angle Angle buffer.
+ * @noreturn
+ */
+native GetVectorAngles(const Float:vec[3], Float:angle[3]);
+
+/**
+ * Returns direction vectors from a vector.
+ *
+ * @param vec Vector.
+ * @param right Right vector buffer or NULL_VECTOR.
+ * @param up Up vector buffer or NULL_VECTOR.
+ * @noreturn
+ */
+native GetVectorVectors(const Float:vec[3], Float:right[3], Float:up[3]);
+
+/**
+ * Adds two vectors. It is safe to use either input buffer as an output
+ * buffer.
+ *
+ * @param vec1 First vector.
+ * @param vec2 Second vector.
+ * @param result Result buffer.
+ * @noreturn
+ */
+stock AddVectors(const Float:vec1[3], const Float:vec2[3], Float:result[3])
+{
+ result[0] = vec1[0] + vec2[0];
+ result[1] = vec1[1] + vec2[1];
+ result[2] = vec1[2] + vec2[2];
+}
+
+/**
+ * Subtracts a vector from another vector. It is safe to use either input
+ * buffer as an output buffer.
+ *
+ * @param vec1 First vector.
+ * @param vec2 Second vector to subtract from first.
+ * @param result Result buffer.
+ * @noreturn
+ */
+stock SubtractVectors(const Float:vec1[3], const Float:vec2[3], Float:result[3])
+{
+ result[0] = vec1[0] - vec2[0];
+ result[1] = vec1[1] - vec2[1];
+ result[2] = vec1[2] - vec2[2];
+}
+
+/**
+ * Scales a vector.
+ *
+ * @param vec Vector.
+ * @param scale Scale value.
+ * @noreturn
+ */
+stock ScaleVector(Float:vec[3], Float:scale)
+{
+ vec[0] *= scale;
+ vec[1] *= scale;
+ vec[2] *= scale;
+}
+
+/**
+ * Negatives a vector.
+ *
+ * @param vec Vector.
+ * @noreturn
+ */
+stock NegateVector(Float:vec[3])
+{
+ vec[0] = -vec[0];
+ vec[1] = -vec[1];
+ vec[2] = -vec[2];
+}
+
+/**
+ * Builds a vector from two points by subtracting the points.
+ *
+ * @param pt1 First point (to be subtracted from the second).
+ * @param pt2 Second point.
+ * @param output Output vector buffer.
+ * @noreturn
+ */
+stock MakeVectorFromPoints(const Float:pt1[3], const Float:pt2[3], Float:output[3])
+{
+ output[0] = pt2[0] - pt1[0];
+ output[1] = pt2[1] - pt1[1];
+ output[2] = pt2[2] - pt1[2];
+}
diff --git a/sourcemod-1.5-dev/scripting/include/version.inc b/sourcemod-1.5-dev/scripting/include/version.inc
new file mode 100644
index 0000000..b69d5c7
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/version.inc
@@ -0,0 +1,49 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This file is part of the SourceMod/SourcePawn SDK.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or <http://www.sourcemod.net/license.php>.
+ *
+ * Version: $Id$
+ */
+
+#if defined _version_included
+ #endinput
+#endif
+#define _version_included
+
+#tryinclude <version_auto>
+
+#if !defined _auto_version_included
+#define SOURCEMOD_V_TAG "manual"
+#define SOURCEMOD_V_REV 0
+#define SOURCEMOD_V_CSET "0"
+#define SOURCEMOD_V_MAJOR 1 /**< SourceMod Major version */
+#define SOURCEMOD_V_MINOR 6 /**< SourceMod Minor version */
+#define SOURCEMOD_V_RELEASE 0 /**< SourceMod Release version */
+
+#define SOURCEMOD_VERSION "1.6.0-manual" /**< SourceMod version string (major.minor.release-tag) */
+#endif
diff --git a/sourcemod-1.5-dev/scripting/include/version_auto.inc b/sourcemod-1.5-dev/scripting/include/version_auto.inc
new file mode 100644
index 0000000..16dd8d2
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/include/version_auto.inc
@@ -0,0 +1,15 @@
+
+#if defined _auto_version_included
+ #endinput
+#endif
+#define _auto_version_included
+
+#define SOURCEMOD_V_TAG ""
+#define SOURCEMOD_V_CSET "95ab81f"
+#define SOURCEMOD_V_MAJOR 1
+#define SOURCEMOD_V_MINOR 6
+#define SOURCEMOD_V_RELEASE 0
+#define SOURCEMOD_V_REV 4525
+
+#define SOURCEMOD_VERSION "1.6.0"
+ \ No newline at end of file
diff --git a/sourcemod-1.5-dev/scripting/ljstats.smx b/sourcemod-1.5-dev/scripting/ljstats.smx
new file mode 100644
index 0000000..feedd3b
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/ljstats.smx
Binary files differ
diff --git a/sourcemod-1.5-dev/scripting/ljstats.sp b/sourcemod-1.5-dev/scripting/ljstats.sp
new file mode 100644
index 0000000..48eadb5
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/ljstats.sp
@@ -0,0 +1,4375 @@
+#include <sourcemod>
+#include <sdktools>
+#include <clientprefs>
+#include <sdkhooks>
+#include <smlib>
+#include <morecolors>
+
+//#define DEBUG
+//#define LJSERV
+
+#pragma semicolon 1
+
+#define MIN(%0,%1) (%0 > %1 ? %1 : %0)
+#define MAX(%0,%1) (%0 < %1 ? %1 : %0)
+
+#define LJSTATS_VERSION "2.0.1"
+
+#define LJTOP_DIR "configs/ljstats/"
+#define LJTOP_FILE "ljtop.txt"
+#define LJTOP_NUM_ENTRIES 50
+#define LJSOUND_NUM 5
+#define MAX_STRAFES 50
+#define BHOP_TIME 0.3
+#define STAMINA_RECHARGE_TIME 0.58579
+#define SW_ANGLE_THRESHOLD 20.0
+#define LJ_HEIGHT_DELTA_MIN -0.01 // Dropjump limit
+#define LJ_HEIGHT_DELTA_MAX 1.5 // Upjump limit
+#define CJ_HEIGHT_DELTA_MIN -0.01
+#define CJ_HEIGHT_DELTA_MAX 1.5
+#define WJ_HEIGHT_DELTA_MIN -0.01
+#define WJ_HEIGHT_DELTA_MAX 1.5
+#define BJ_HEIGHT_DELTA_MIN -2.0 // dynamic pls
+#define BJ_HEIGHT_DELTA_MAX 2.0
+#define LAJ_HEIGHT_DELTA_MIN -6.0
+#define LAJ_HEIGHT_DELTA_MAX 0.0
+#define HUD_HINT_SIZE 256
+
+public Plugin:myinfo =
+{
+ name = "ljstats",
+ author = "Miu",
+ description = "longjump stats",
+ version = LJSTATS_VERSION,
+ url = "https://forums.alliedmods.net/showthread.php?p=2060983"
+}
+
+enum PlayerState
+{
+ bool:bLJEnabled,
+ bool:bHidePanel,
+ bool:bHideBhopPanel,
+ bool:bShowBhopStats,
+ bool:bBeam,
+ bool:bSound,
+ bool:bBlockMode,
+ nVerbosity,
+ bool:bShowAllJumps,
+ #if defined LJSERV
+ bool:bShowPrestrafeHint,
+ #endif
+
+ Float:fBlockDistance,
+ Float:vBlockNormal[2],
+ Float:vBlockEndPos[3],
+ bool:bFailedBlock,
+
+ bool:bDuck,
+ bool:bLastDuckState,
+ bool:bSecondLastDuckState,
+
+ JUMP_DIRECTION:JumpDir,
+ ILLEGAL_JUMP_FLAGS:IllegalJumpFlags,
+
+ JUMP_TYPE:LastJumpType,
+ JUMP_TYPE:JumpType,
+ Float:fLandTime,
+ Float:fLastJumpHeightDelta,
+ nBhops,
+
+ bool:bOnGround,
+ bool:bOnLadder,
+
+ Float:fEdge,
+ Float:vJumpOrigin[3],
+ Float:fWJDropPre,
+ Float:fPrestrafe,
+ Float:fJumpDistance,
+ Float:fHeightDelta,
+ Float:fJumpHeight,
+ Float:fSync,
+ Float:fMaxSpeed,
+ Float:fFinalSpeed,
+ Float:fTrajectory,
+ Float:fGain,
+ Float:fLoss,
+
+ STRAFE_DIRECTION:CurStrafeDir,
+ nStrafes,
+ STRAFE_DIRECTION:StrafeDir[MAX_STRAFES],
+ Float:fStrafeGain[MAX_STRAFES],
+ Float:fStrafeLoss[MAX_STRAFES],
+ Float:fStrafeSync[MAX_STRAFES],
+ nStrafeTicks[MAX_STRAFES],
+ nStrafeTicksSynced[MAX_STRAFES],
+ nTotalTicks,
+ Float:fTotalAngle,
+ Float:fSyncedAngle,
+
+ bool:bStamina,
+ nJumpTick,
+ nLastAerialTick,
+
+ Float:vLastOrigin[3],
+ Float:vLastAngles[3],
+ Float:vLastVelocity[3],
+
+ String:strHUDHint[HUD_HINT_SIZE / 4], // string characters are stored as cells
+
+ Float:fPersonalBest,
+
+ nSpectators,
+ nSpectatorTarget,
+
+ GAP_SELECTION_MODE:GapSelectionMode,
+ Float:vGapPoint1[3],
+ LastButtons,
+}
+
+#define LJTOP_MIN_NUM_STATS_0 7
+#define LJTOP_MIN_NUM_STATS_1 14
+#define LJTOP_MAX_NUM_STATS 14 + 16 * 5
+#define LJTOP_MAX_STRAFES 16
+
+enum TopStats
+{
+ String:m_strName[64 / 4],
+ String:m_strSteamID[32 / 4],
+ Float:m_fDistance,
+ Float:m_fPrestrafe,
+ m_nStrafes, //
+ Float:m_fSync,
+ Float:m_fMaxSpeed,
+ m_nTotalTicks,
+ Float:m_fSyncedAngle,
+ Float:m_fTotalAngle, //
+ Float:m_fHeightDelta,
+ Float:m_fBlockDistance,
+ Float:m_fTrajectory,
+ m_nTimestamp,
+
+ STRAFE_DIRECTION:m_StrafeDir[LJTOP_MAX_STRAFES],
+ Float:m_fStrafeGain[LJTOP_MAX_STRAFES],
+ Float:m_fStrafeLoss[LJTOP_MAX_STRAFES],
+ m_nStrafeTicks[LJTOP_MAX_STRAFES],
+ Float:m_fStrafeSync[LJTOP_MAX_STRAFES],
+}
+
+enum ILLEGAL_JUMP_FLAGS
+{
+ IJF_NONE = 0,
+ IJF_WORLD = 1 << 0,
+ IJF_BOOSTER = 1 << 1,
+ IJF_GRAVITY = 1 << 2,
+ IJF_TELEPORT = 1 << 3,
+ IJF_LAGGEDMOVEMENTVALUE = 1 << 4,
+ IJF_PRESTRAFE = 1 << 5,
+ IJF_SCOUT = 1 << 6,
+ IJF_NOCLIP = 1 << 7,
+}
+
+enum JUMP_TYPE
+{
+ JT_LONGJUMP,
+ JT_COUNTJUMP,
+ JT_WEIRDJUMP,
+ JT_BHOPJUMP,
+ JT_LADDERJUMP,
+ JT_BHOP,
+ JT_DROP,
+ JT_END,
+}
+
+enum JUMP_DIRECTION
+{
+ JD_NONE, // Indeterminate
+ JD_NORMAL,
+ JD_FORWARDS = JD_NORMAL,
+ JD_SIDEWAYS,
+ JD_BACKWARDS,
+ JD_END,
+}
+
+enum STRAFE_DIRECTION
+{
+ SD_NONE,
+ SD_W,
+ SD_D,
+ SD_A,
+ SD_S,
+ SD_WA,
+ SD_WD,
+ SD_SA,
+ SD_SD,
+ SD_END,
+}
+
+enum GAP_SELECTION_MODE
+{
+ GSM_NONE,
+ GSM_GAP,
+ GSM_GAPSECOND,
+ GSM_BLOCKGAP,
+}
+
+enum LJTOP_TABLE
+{
+ LT_LJ,
+ LT_BLOCKLJ,
+ LT_SWLJ,
+ LT_BWLJ,
+ LT_CJ,
+ LT_BJ,
+ LT_LAJ,
+ LT_STRAFEBHOP,
+ LT_END,
+}
+
+new String:g_strLJTopTags[LT_END][] =
+{
+ "lj",
+ "blj",
+ "swlj",
+ "bwlj",
+ "cj",
+ "bj",
+ "laj",
+ "strafebhop"
+};
+
+new String:g_strLJTopTableName[LT_END][] =
+{
+ "Longjump",
+ "Block longjump",
+ "Sideways longjump",
+ "Backwards longjump",
+ "Countjump",
+ "Bhopjump",
+ "Ladderjump",
+ "Multibhop"
+};
+
+new String:g_strLJTopOutput[LT_END][] =
+{
+ "lj",
+ "block lj",
+ "sideways lj",
+ "backwards lj",
+ "countjump",
+ "bhopjump",
+ "ladderjump",
+ "multibhop"
+};
+
+new String:g_strJumpType[JT_END][] =
+{
+ "Longjump",
+ "Countjump",
+ "Weirdjump",
+ "Bhopjump",
+ "Ladderjump",
+ "Bhop",
+ "Drop"
+};
+
+new String:g_strJumpTypeLwr[JT_END][] =
+{
+ "longjump",
+ "countjump",
+ "weirdjump",
+ "bhopjump",
+ "ladderjump",
+ "bhop",
+ "drop"
+};
+
+new String:g_strJumpTypeShort[JT_END][] =
+{
+ "LJ",
+ "CJ",
+ "WJ",
+ "BJ",
+ "LAJ",
+ "Bhop",
+ "Drop"
+};
+
+new const Float:g_fHeightDeltaMin[JT_END] =
+{
+ LJ_HEIGHT_DELTA_MIN,
+ LJ_HEIGHT_DELTA_MIN,
+ WJ_HEIGHT_DELTA_MIN,
+ BJ_HEIGHT_DELTA_MIN,
+ LAJ_HEIGHT_DELTA_MIN,
+ -3.402823466e38,
+ -3.402823466e38
+};
+
+new const Float:g_fHeightDeltaMax[JT_END] =
+{
+ LJ_HEIGHT_DELTA_MAX,
+ LJ_HEIGHT_DELTA_MAX,
+ WJ_HEIGHT_DELTA_MAX,
+ BJ_HEIGHT_DELTA_MAX,
+ LAJ_HEIGHT_DELTA_MAX,
+ 3.402823466e38,
+ 3.402823466e38
+};
+
+// SourcePawn is silly
+#define HEIGHT_DELTA_MIN(%0) (Float:g_fHeightDeltaMin[Float:%0])
+#define HEIGHT_DELTA_MAX(%0) (Float:g_fHeightDeltaMax[Float:%0])
+
+new g_PlayerStates[MAXPLAYERS + 1][PlayerState];
+
+new g_LJTop[LT_END][LJTOP_NUM_ENTRIES][TopStats];
+
+new Handle:g_hLJTopMainMenu = INVALID_HANDLE;
+new Handle:g_hLJTopMenus[LT_END] = INVALID_HANDLE;
+
+new g_BeamModel;
+
+new Handle:g_hCvarColorMin = INVALID_HANDLE;
+new Handle:g_hCvarColorMax = INVALID_HANDLE;
+new Handle:g_hCvarLJMin = INVALID_HANDLE;
+new Handle:g_hCvarLJMax = INVALID_HANDLE;
+new Handle:g_hCvarNonLJMax = INVALID_HANDLE;
+new Handle:g_hCvarLJMaxPrestrafe = INVALID_HANDLE;
+new Handle:g_hCvarLJScoutStats = INVALID_HANDLE;
+new Handle:g_hCvarLJNoDuckMin = INVALID_HANDLE;
+new Handle:g_hCvarLJClientMin = INVALID_HANDLE;
+new Handle:g_hCvarWJMin = INVALID_HANDLE;
+new Handle:g_hCvarWJDropMax = INVALID_HANDLE;
+new Handle:g_hCvarBJMin = INVALID_HANDLE;
+new Handle:g_hCvarLAJMin = INVALID_HANDLE;
+new Handle:g_hCvarPrintFailedBlockStats = INVALID_HANDLE;
+new Handle:g_hCvarShowBhopStats = INVALID_HANDLE;
+new Handle:g_hCvarOutput16Style = INVALID_HANDLE;
+new Handle:g_hCvarVerbosity = INVALID_HANDLE;
+new Handle:g_hCvarLJTopAllowEasyBJ = INVALID_HANDLE;
+new Handle:g_hCvarLJSound = INVALID_HANDLE;
+new Handle:g_hCvarLJSound1 = INVALID_HANDLE;
+new Handle:g_hCvarLJSound2 = INVALID_HANDLE;
+new Handle:g_hCvarLJSound3 = INVALID_HANDLE;
+new Handle:g_hCvarLJSound4 = INVALID_HANDLE;
+new Handle:g_hCvarLJSound5 = INVALID_HANDLE;
+new Handle:g_hCvarLJSound1File = INVALID_HANDLE;
+new Handle:g_hCvarLJSound2File = INVALID_HANDLE;
+new Handle:g_hCvarLJSound3File = INVALID_HANDLE;
+new Handle:g_hCvarLJSound4File = INVALID_HANDLE;
+new Handle:g_hCvarLJSound5File = INVALID_HANDLE;
+new Handle:g_hCvarLJSoundToAll[5] = {INVALID_HANDLE, ...};
+
+new Handle:g_hCvarMaxspeed = INVALID_HANDLE;
+new Handle:g_hCvarEnableBunnyHopping = INVALID_HANDLE;
+
+new Handle:g_hCookieDefaultsSet = INVALID_HANDLE;
+new Handle:g_hCookieLJEnabled = INVALID_HANDLE;
+new Handle:g_hCookieBlockMode = INVALID_HANDLE;
+new Handle:g_hCookieBeam = INVALID_HANDLE;
+new Handle:g_hCookieSound = INVALID_HANDLE;
+new Handle:g_hCookieHidePanel = INVALID_HANDLE;
+new Handle:g_hCookieHideBhopPanel = INVALID_HANDLE;
+new Handle:g_hCookieShowBhopStats = INVALID_HANDLE;
+new Handle:g_hCookieVerbosity = INVALID_HANDLE;
+new Handle:g_hCookieShowAllJumps = INVALID_HANDLE;
+#if defined LJSERV
+new Handle:g_hCookieShowPrestrafeHint = INVALID_HANDLE;
+#endif
+new Handle:g_hCookiePersonalBest = INVALID_HANDLE;
+
+new g_ColorMin[3] = {0xAD, 0xD8, 0xE6}; // Lightblue!
+new g_ColorMax[3] = {0x00, 0x00, 0xFF};
+new Float:g_fLJMin = 260.0;
+new Float:g_fLJMax = 275.0;
+new Float:g_fNonLJMax = 275.0;
+new Float:g_fLJMaxPrestrafe = 280.0;
+new bool:g_bLJScoutStats = false;
+new Float:g_fLJNoDuckMin = 256.0;
+new Float:g_fLJClientMin = 0.0;
+new Float:g_fWJMin = 270.0;
+new Float:g_fWJDropMax = 30.0;
+new Float:g_fBJMin = 270.0;
+new Float:g_fLAJMin = 140.0;
+new g_nVerbosity = 2;
+new bool:g_bPrintFailedBlockStats = true;
+new bool:g_bShowBhopStats = true;
+new bool:g_bOutput16Style = false;
+new bool:g_bLJTopAllowEasyBJ = true;
+new bool:g_bLJSound = true;
+new Float:g_fLJSound[5] = {260.0, 265.0, 268.0, 270.0, 0.0};
+new String:g_strLJSoundFile[5][64] = {"misc/perfect.wav", "misc/mod_wickedsick.wav", "misc/mod_godlike.wav", "misc/holyshit.wav", ""};
+new bool:g_bLJSoundToAll[5] = false;
+
+new Float:g_fMaxspeed = 320.0; // sv_maxspeed
+new bool:g_bEnableBunnyHopping = true; // sv_enablebunnyhopping
+
+Handle:CreateCvar(String:strName[], String:strValue[])
+{
+ new Handle:hCvar = CreateConVar(strName, strValue);
+ HookConVarChange(hCvar, OnCvarChange);
+
+ return hCvar;
+}
+
+public OnPluginStart()
+{
+ DB_Connect();
+ DB_CreateTables();
+ DB_LoadLJTop();
+
+ CreateConVar("mljstats_version", LJSTATS_VERSION, "ljstats version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY);
+
+ g_hCvarColorMin = CreateCvar("ljstats_color_min", "ADD8E6");
+ g_hCvarColorMax = CreateCvar("ljstats_color_max", "0000FF");
+ g_hCvarLJMin = CreateCvar("ljstats_lj_min", "260");
+ g_hCvarLJMax = CreateCvar("ljstats_lj_max", "275");
+ g_hCvarNonLJMax = CreateCvar("ljstats_nonlj_max", "275");
+ g_hCvarLJMaxPrestrafe = CreateCvar("ljstats_lj_max_prestrafe", "280");
+ g_hCvarLJScoutStats = CreateCvar("ljstats_lj_scout_stats", "0");
+ g_hCvarLJNoDuckMin = CreateCvar("ljstats_lj_noduck_min", "256");
+ g_hCvarLJClientMin = CreateCvar("ljstats_lj_client_min", "0.0");
+ g_hCvarWJMin = CreateCvar("ljstats_wj_min", "270");
+ g_hCvarWJDropMax = CreateCvar("ljstats_wj_drop_max", "30.0");
+ g_hCvarBJMin = CreateCvar("ljstats_bj_min", "270");
+ g_hCvarLAJMin = CreateCvar("ljstats_laj_min", "140");
+ g_hCvarVerbosity = CreateCvar("ljstats_verbosity", "2");
+ g_hCvarPrintFailedBlockStats = CreateCvar("ljstats_print_failed_block_stats", "1");
+ g_hCvarShowBhopStats = CreateCvar("ljstats_show_bhop_stats", "0");
+ g_hCvarOutput16Style = CreateCvar("ljstats_output_1.6_style", "0");
+ g_hCvarLJTopAllowEasyBJ = CreateCvar("ljstats_ljtop_allow_easybhopjump", "1");
+ g_hCvarLJSound = CreateCvar("ljstats_lj_sound", "1");
+ g_hCvarLJSound1 = CreateCvar("ljstats_lj_sound1", "260");
+ g_hCvarLJSound2 = CreateCvar("ljstats_lj_sound2", "265");
+ g_hCvarLJSound3 = CreateCvar("ljstats_lj_sound3", "268");
+ g_hCvarLJSound4 = CreateCvar("ljstats_lj_sound4", "270");
+ g_hCvarLJSound5 = CreateCvar("ljstats_lj_sound5", "0");
+ g_hCvarLJSound1File = CreateCvar("ljstats_lj_sound1_file", g_strLJSoundFile[0]);
+ g_hCvarLJSound2File = CreateCvar("ljstats_lj_sound2_file", g_strLJSoundFile[1]);
+ g_hCvarLJSound3File = CreateCvar("ljstats_lj_sound3_file", g_strLJSoundFile[2]);
+ g_hCvarLJSound4File = CreateCvar("ljstats_lj_sound4_file", g_strLJSoundFile[3]);
+ g_hCvarLJSound5File = CreateCvar("ljstats_lj_sound5_file", g_strLJSoundFile[4]);
+ g_hCvarLJSoundToAll[0] = CreateCvar("ljstats_lj_sound1_to_all", "0");
+ g_hCvarLJSoundToAll[1] = CreateCvar("ljstats_lj_sound2_to_all", "0");
+ g_hCvarLJSoundToAll[2] = CreateCvar("ljstats_lj_sound3_to_all", "0");
+ g_hCvarLJSoundToAll[3] = CreateCvar("ljstats_lj_sound4_to_all", "0");
+ g_hCvarLJSoundToAll[4] = CreateCvar("ljstats_lj_sound5_to_all", "0");
+
+ g_hCvarMaxspeed = FindConVar("sv_maxspeed");
+ if(g_hCvarMaxspeed)
+ {
+ g_fMaxspeed = GetConVarFloat(g_hCvarMaxspeed);
+ }
+
+ HookConVarChange(g_hCvarMaxspeed, OnCvarChange);
+
+ g_hCvarEnableBunnyHopping = FindConVar("sv_enablebunnyhopping");
+ if(g_hCvarEnableBunnyHopping)
+ {
+ g_bEnableBunnyHopping = GetConVarBool(g_hCvarEnableBunnyHopping);
+ }
+
+ HookConVarChange(g_hCvarEnableBunnyHopping, OnCvarChange);
+
+ CreateNative("LJStats_CancelJump", Native_CancelJump);
+
+ HookEvent("player_jump", Event_PlayerJump);
+ HookEvent("player_death", Event_PlayerDeath);
+
+ RegConsoleCmd("sm_ljhelp", Command_LJHelp);
+ #if !defined LJSERV
+ RegConsoleCmd("sm_lj", Command_LJ);
+ #else
+ RegConsoleCmd("sm_lj", Command_LJSettings);
+ #endif
+ RegConsoleCmd("sm_ljsettings", Command_LJSettings);
+ RegConsoleCmd("sm_ljs", Command_LJSettings);
+ RegConsoleCmd("sm_ljpanel", Command_LJPanel);
+ RegConsoleCmd("sm_ljbeam", Command_LJBeam);
+ RegConsoleCmd("sm_ljblock", Command_LJBlock);
+ RegConsoleCmd("sm_ljb", Command_LJBlock);
+ RegConsoleCmd("sm_ljsound", Command_LJSound);
+ RegConsoleCmd("sm_ljver", Command_LJVersion);
+ RegConsoleCmd("sm_ljversion", Command_LJVersion);
+ RegConsoleCmd("sm_ljtop", Command_LJTop);
+ #if defined LJSERV
+ RegConsoleCmd("sm_wr", Command_LJTop);
+ #endif
+ RegAdminCmd("sm_ljtopdelete", Command_LJTopDelete, ADMFLAG_RCON);
+ RegConsoleCmd("sm_gap", Command_Gap);
+ RegConsoleCmd("sm_blockgap", Command_BlockGap);
+ RegConsoleCmd("sm_tele", Command_Tele);
+ RegAdminCmd("sm_ljtopdeleteall", Command_Delete, ADMFLAG_RCON);
+ RegConsoleCmd("sm_ljpb", Command_PersonalBest);
+ RegConsoleCmd("sm_pb", Command_PersonalBest);
+ RegConsoleCmd("sm_personalbest", Command_PersonalBest);
+ RegConsoleCmd("sm_pr", Command_PersonalBest);
+ RegConsoleCmd("sm_resetpersonalbest", Command_ResetPersonalBest);
+ RegAdminCmd("sm_ljtoploadfromfile", Command_LJTopLoadFromFile, ADMFLAG_RCON);
+
+ g_hCookieDefaultsSet = RegClientCookie("ljstats_defaultsset", "ljstats_defaultsset", CookieAccess_Public);
+ g_hCookieLJEnabled = RegClientCookie("ljstats_ljenabled", "ljstats_ljenabled", CookieAccess_Public);
+ g_hCookieBlockMode = RegClientCookie("ljstats_blockmode", "ljstats_blockmode", CookieAccess_Public);
+ g_hCookieBeam = RegClientCookie("ljstats_beam", "ljstats_beam", CookieAccess_Public);
+ g_hCookieSound = RegClientCookie("ljstats_sound", "ljstats_sound", CookieAccess_Public);
+ g_hCookieHidePanel = RegClientCookie("ljstats_hidepanel", "ljstats_hidepanel", CookieAccess_Public);
+ g_hCookieHideBhopPanel = RegClientCookie("ljstats_hidebhoppanel", "ljstats_hidebhoppanel", CookieAccess_Public);
+ g_hCookieShowBhopStats = RegClientCookie("ljstats_showbhopstats", "ljstats_showbhopstats", CookieAccess_Public);
+ g_hCookieVerbosity = RegClientCookie("ljstats_verbosity", "ljstats_verbosity", CookieAccess_Public);
+ g_hCookieShowAllJumps = RegClientCookie("ljstats_showalljumps", "ljstats_showalljumps", CookieAccess_Public);
+ #if defined LJSERV
+ g_hCookieShowPrestrafeHint = RegClientCookie("ljstats_showprestrafehint", "ljstats_showprestrafehint", CookieAccess_Public);
+ #endif
+ g_hCookiePersonalBest = RegClientCookie("ljstats_personalbest", "ljstats_personalbest", CookieAccess_Private);
+
+ for(new i = 1; i < MaxClients; i++)
+ {
+ if(IsClientInGame(i))
+ {
+ OnClientPutInServer(i);
+ OnClientCookiesCached(i);
+ }
+ }
+}
+
+/*
+enum TopStats
+{
+ String:m_strName[64 / 4],
+ String:m_strSteamID[32 / 4],
+ Float:m_fDistance,
+ Float:m_fPrestrafe,
+ m_nStrafes, //
+ Float:m_fSync,
+ Float:m_fMaxSpeed,
+ m_nTotalTicks,
+ Float:m_fSyncedAngle,
+ Float:m_fTotalAngle, //
+ Float:m_fHeightDelta,
+ Float:m_fBlockDistance,
+ Float:m_fTrajectory,
+ m_nTimestamp,
+
+ STRAFE_DIRECTION:m_StrafeDir[LJTOP_MAX_STRAFES],
+ Float:m_fStrafeGain[LJTOP_MAX_STRAFES],
+ Float:m_fStrafeLoss[LJTOP_MAX_STRAFES],
+ m_nStrafeTicks[LJTOP_MAX_STRAFES],
+ Float:m_fStrafeSync[LJTOP_MAX_STRAFES],
+}
+*/
+
+new const String:SQL_CreateLJTopTable[] = "CREATE TABLE IF NOT EXISTS ljtop (ljtable VARCHAR(16), name VARCHAR(64), steamid VARCHAR(32), distance FLOAT, prestrafe FLOAT, strafes INT, sync FLOAT, maxspeed FLOAT, totalticks FLOAT, syncedangle FLOAT, totalangle FLOAT, heightdelta FLOAT, blockdistance FLOAT, trajectory FLOAT, timestamp INT)";
+new const String:SQL_CreateLJTopStrafesTable[] = "CREATE TABLE IF NOT EXISTS ljtopstrafes (ljtable VARCHAR(16), rank INTEGER, strafenum INTEGER, dir VARCHAR(3), gain FLOAT, loss FLOAT, ticks INT, sync FLOAT)";
+new const String:SQL_LoadLJTop[] = "SELECT * FROM ljtop ORDER BY distance DESC";
+new const String:SQL_LoadLJTopStrafes[] = "SELECT * FROM ljtopstrafes";
+new const String:SQL_DeleteLJTop[] = "DELETE FROM ljtop";
+new const String:SQL_DeleteLJTopStrafes[] = "DELETE FROM ljtopstrafes";
+
+new Handle:g_DB = INVALID_HANDLE;
+
+DB_Connect()
+{
+ if (g_DB != INVALID_HANDLE)
+ {
+ CloseHandle(g_DB);
+ }
+
+ decl String:error[255];
+ g_DB = SQL_Connect("ljstats", true, error, sizeof(error));
+
+ if (g_DB == INVALID_HANDLE)
+ {
+ LogError(error);
+ CloseHandle(g_DB);
+ }
+}
+
+DB_CreateTables()
+{
+ new Handle:hQ = SQL_Query(g_DB, SQL_CreateLJTopTable);
+
+ if(hQ == INVALID_HANDLE)
+ {
+ decl String:error[255];
+ SQL_GetError(g_DB, error, sizeof(error));
+ LogError("DB_CreateTables failed: %s", error);
+ return;
+ }
+
+ SQL_Query(g_DB, SQL_CreateLJTopStrafesTable);
+
+ if(hQ == INVALID_HANDLE)
+ {
+ decl String:error[255];
+ SQL_GetError(g_DB, error, sizeof(error));
+ LogError("DB_CreateTables failed: %s", error);
+ return;
+ }
+}
+
+DB_LoadLJTop()
+{
+ SQL_TQuery(g_DB, DB_LoadLJTop_Callback, SQL_LoadLJTop);
+ SQL_TQuery(g_DB, DB_LoadLJTopStrafes_Callback, SQL_LoadLJTopStrafes);
+}
+
+public DB_LoadLJTop_Callback(Handle:owner, Handle:hndl, String:error[], any:pack)
+{
+ if(hndl == INVALID_HANDLE)
+ {
+ LogError("DB_LoadLJTop failed: %s", error);
+ return;
+ }
+
+ new rows = SQL_GetRowCount(hndl);
+
+ new it[LT_END] = {0, ...};
+
+ for(new i = 0; i < rows; i++)
+ {
+ SQL_FetchRow(hndl);
+
+ decl String:table[16], String:name[64], String:steamid[32];
+
+ SQL_FetchStringByName(hndl, "ljtable", table, sizeof(table));
+
+ new iTable = _:GetLJTopTable(table);
+
+ if(it[iTable] > LJTOP_NUM_ENTRIES - 1)
+ {
+ LogError("Too many rows for table %s", table);
+ return;
+ }
+
+ if (iTable == -1)
+ {
+ LogError("DB_LoadLJTop: Invalid table %s", table);
+ return;
+ }
+
+ SQL_FetchStringByName(hndl, "name", name, sizeof(name));
+ SQL_FetchStringByName(hndl, "steamid", steamid, sizeof(steamid));
+
+ strcopy(g_LJTop[iTable][it[iTable]][m_strName], 64, name);
+ strcopy(g_LJTop[iTable][it[iTable]][m_strSteamID], 32, steamid);
+
+ g_LJTop[iTable][it[iTable]][m_fDistance] = SQL_FetchFloatByName(hndl, "distance");
+ g_LJTop[iTable][it[iTable]][m_fPrestrafe] = SQL_FetchFloatByName(hndl, "prestrafe");
+ g_LJTop[iTable][it[iTable]][m_nStrafes] = SQL_FetchIntByName(hndl, "strafes");
+ g_LJTop[iTable][it[iTable]][m_fSync] = SQL_FetchFloatByName(hndl, "sync");
+ g_LJTop[iTable][it[iTable]][m_fMaxSpeed] = SQL_FetchFloatByName(hndl, "maxspeed");
+ g_LJTop[iTable][it[iTable]][m_nTotalTicks] = SQL_FetchIntByName(hndl, "totalticks");
+ g_LJTop[iTable][it[iTable]][m_fSyncedAngle] = SQL_FetchFloatByName(hndl, "syncedangle");
+ g_LJTop[iTable][it[iTable]][m_fTotalAngle] = SQL_FetchFloatByName(hndl, "totalangle");
+ g_LJTop[iTable][it[iTable]][m_fBlockDistance] = SQL_FetchFloatByName(hndl, "blockdistance");
+ g_LJTop[iTable][it[iTable]][m_fTrajectory] = SQL_FetchFloatByName(hndl, "trajectory");
+ g_LJTop[iTable][it[iTable]][m_nTimestamp] = SQL_FetchIntByName(hndl, "timestamp");
+
+ it[iTable]++;
+ }
+
+ LJTopCreateMainMenu();
+ for(new LJTOP_TABLE:i; i < LT_END; i++)
+ {
+ LJTopCreateMenu(i);
+ }
+}
+
+public DB_LoadLJTopStrafes_Callback(Handle:owner, Handle:hndl, String:error[], any:pack)
+{
+ if(hndl == INVALID_HANDLE)
+ {
+ LogError("DB_LoadLJTopStrafes failed: %s", error);
+ return;
+ }
+
+ new rows = SQL_GetRowCount(hndl);
+
+ for(new i = 0; i < rows; i++)
+ {
+ SQL_FetchRow(hndl);
+
+ decl String:table[16];
+
+ SQL_FetchStringByName(hndl, "ljtable", table, sizeof(table));
+
+ new iTable = -1;
+
+ for(new LJTOP_TABLE:j; j < LT_END; j++)
+ {
+ if(!strcmp(g_strLJTopTags[j], table))
+ {
+ iTable = _:j;
+ break;
+ }
+ }
+
+ if (iTable == -1)
+ {
+ LogError("DB_LoadLJTop: Invalid table %s", table);
+ return;
+ }
+
+ new iEntry = SQL_FetchIntByName(hndl, "rank");
+ new iStrafe = SQL_FetchIntByName(hndl, "strafenum");
+
+ decl String:key[3];
+ SQL_FetchStringByName(hndl, "dir", key, sizeof(key));
+
+ g_LJTop[iTable][iEntry][m_StrafeDir][iStrafe] = GetStrafeDir(key);
+ g_LJTop[iTable][iEntry][m_fStrafeGain][iStrafe] = SQL_FetchFloatByName(hndl, "gain");
+ g_LJTop[iTable][iEntry][m_fStrafeLoss][iStrafe] = SQL_FetchFloatByName(hndl, "loss");
+ g_LJTop[iTable][iEntry][m_nStrafeTicks][iStrafe] = SQL_FetchIntByName(hndl, "ticks");
+ g_LJTop[iTable][iEntry][m_fStrafeSync][iStrafe] = SQL_FetchFloatByName(hndl, "sync");
+ }
+}
+
+DB_SaveLJTop()
+{
+ SQL_TQuery(g_DB, DB_EmptyCallback, SQL_DeleteLJTop);
+ SQL_TQuery(g_DB, DB_EmptyCallback, SQL_DeleteLJTopStrafes);
+
+ new Handle:hTxn = SQL_CreateTransaction();
+
+ decl String:sQuery[1024];
+
+ for(new LJTOP_TABLE:i; i < LT_END; i++)
+ {
+ for (new j = 0; j < LJTOP_NUM_ENTRIES; j++)
+ {
+ if (g_LJTop[i][j][m_strSteamID][0] == 0)
+ continue;
+
+ decl String:EscapedName[512];
+ if (!SQL_EscapeString(g_DB, g_LJTop[i][j][m_strName], EscapedName, sizeof(EscapedName)))
+ {
+ LogError("Failed to escape %s's name when writing ljs to database! Writing name without quotes instead", g_LJTop[i][j][m_strName]);
+ strcopy(EscapedName, sizeof(EscapedName), g_LJTop[i][j][m_strName]);
+ new index = 0;
+ while ((index = StrContains(EscapedName, "'")) != -1)
+ {
+ strcopy(EscapedName[index], sizeof(EscapedName) - index, EscapedName[index + 1]);
+ }
+ }
+ FormatEx(sQuery, sizeof(sQuery), "INSERT INTO ljtop (ljtable, name, steamid, distance, prestrafe, strafes, sync, maxspeed, totalticks, syncedangle, totalangle, heightdelta, blockdistance, trajectory, timestamp) VALUES ('%s', '%s', '%s', %f, %f, %d, %f, %f, %d, %f, %f, %f, %f, %f, %d)",
+ g_strLJTopTags[i],
+ EscapedName,
+ g_LJTop[i][j][m_strSteamID],
+ g_LJTop[i][j][m_fDistance],
+ g_LJTop[i][j][m_fPrestrafe],
+ g_LJTop[i][j][m_nStrafes],
+ g_LJTop[i][j][m_fSync],
+ g_LJTop[i][j][m_fMaxSpeed],
+ g_LJTop[i][j][m_nTotalTicks],
+ g_LJTop[i][j][m_fSyncedAngle],
+ g_LJTop[i][j][m_fTotalAngle],
+ g_LJTop[i][j][m_fHeightDelta],
+ g_LJTop[i][j][m_fBlockDistance],
+ g_LJTop[i][j][m_fTrajectory],
+ g_LJTop[i][j][m_nTimestamp]);
+
+ SQL_AddQuery(hTxn, sQuery);
+
+ for (new k = 0; k < g_LJTop[i][j][m_nStrafes]; k++)
+ {
+ decl String:key[3];
+ GetStrafeKey(key, g_LJTop[i][j][m_StrafeDir][k]);
+
+ FormatEx(sQuery, sizeof(sQuery), "INSERT INTO ljtopstrafes (ljtable, rank, strafenum, dir, gain, loss, ticks, sync) VALUES ('%s', %d, %d, '%s', %f, %f, %d, %f)",
+ g_strLJTopTags[i],
+ j,
+ k,
+ key,
+ g_LJTop[i][j][m_fStrafeGain][k],
+ g_LJTop[i][j][m_fStrafeLoss][k],
+ g_LJTop[i][j][m_nStrafeTicks][k],
+ g_LJTop[i][j][m_fStrafeSync][k]);
+
+ SQL_AddQuery(hTxn, sQuery);
+ }
+ }
+ }
+
+ SQL_ExecuteTransaction(g_DB, hTxn, SQLTxnSuccess:-1, DB_TxnFailure);
+}
+
+public DB_EmptyCallback(Handle:owner, Handle:hndl, String:error[], any:pack)
+{
+ if(hndl == INVALID_HANDLE)
+ {
+ LogError(error);
+ }
+}
+
+public DB_TxnFailure(Handle:db, any:data, numQueries, const String:error[], failIndex, any:queryData[])
+{
+ LogError("DB_SaveLJTop: Transaction failed: %s", error);
+}
+
+LJTOP_TABLE:GetLJTopTable(const String:table[])
+{
+ for(new LJTOP_TABLE:j; j < LT_END; j++)
+ {
+ if(!strcmp(g_strLJTopTags[j], table))
+ {
+ return j;
+ }
+ }
+
+ return LJTOP_TABLE:-1;
+}
+
+#define ON_CVAR_CHANGE_BOOL(%0,%1) else if(hCvar == %0) { %1 = bool:StringToInt(strNewValue); }
+#define ON_CVAR_CHANGE_INT(%0,%1) else if(hCvar == %0) { %1 = StringToInt(strNewValue); }
+#define ON_CVAR_CHANGE_FLOAT(%0,%1) else if(hCvar == %0) { %1 = StringToFloat(strNewValue); }
+
+public OnCvarChange(Handle:hCvar, const String:strOldValue[], const String:strNewValue[])
+{
+ if(hCvar == g_hCvarColorMin)
+ {
+ new nColor = StringToInt(strNewValue, 16);
+ g_ColorMin[0] = (nColor & 0xFF0000) >> 16;
+ g_ColorMin[1] = (nColor & 0xFF00) >> 8;
+ g_ColorMin[2] = nColor & 0xFF;
+ }
+ else if(hCvar == g_hCvarColorMax)
+ {
+ new nColor = StringToInt(strNewValue, 16);
+ g_ColorMax[0] = (nColor & 0xFF0000) >> 16;
+ g_ColorMax[1] = (nColor & 0xFF00) >> 8;
+ g_ColorMax[2] = nColor & 0xFF;
+ }
+ ON_CVAR_CHANGE_FLOAT(g_hCvarLJMin, g_fLJMin)
+ ON_CVAR_CHANGE_FLOAT(g_hCvarLJMax, g_fLJMax)
+ ON_CVAR_CHANGE_FLOAT(g_hCvarNonLJMax, g_fNonLJMax)
+ ON_CVAR_CHANGE_FLOAT(g_hCvarLJMaxPrestrafe, g_fLJMaxPrestrafe)
+ ON_CVAR_CHANGE_BOOL(g_hCvarLJScoutStats, g_bLJScoutStats)
+ ON_CVAR_CHANGE_FLOAT(g_hCvarLJNoDuckMin, g_fLJNoDuckMin)
+ ON_CVAR_CHANGE_FLOAT(g_hCvarLJClientMin, g_fLJClientMin)
+ ON_CVAR_CHANGE_FLOAT(g_hCvarWJMin, g_fWJMin)
+ ON_CVAR_CHANGE_FLOAT(g_hCvarWJDropMax, g_fWJDropMax)
+ ON_CVAR_CHANGE_FLOAT(g_hCvarBJMin, g_fBJMin)
+ ON_CVAR_CHANGE_FLOAT(g_hCvarLAJMin, g_fLAJMin)
+ ON_CVAR_CHANGE_INT(g_hCvarVerbosity, g_nVerbosity)
+ ON_CVAR_CHANGE_BOOL(g_hCvarPrintFailedBlockStats, g_bPrintFailedBlockStats)
+ ON_CVAR_CHANGE_BOOL(g_hCvarShowBhopStats, g_bShowBhopStats)
+ ON_CVAR_CHANGE_BOOL(g_hCvarOutput16Style, g_bOutput16Style)
+ ON_CVAR_CHANGE_BOOL(g_hCvarLJTopAllowEasyBJ, g_bLJTopAllowEasyBJ)
+ ON_CVAR_CHANGE_BOOL(g_hCvarLJSound, g_bLJSound)
+ ON_CVAR_CHANGE_FLOAT(g_hCvarLJSound1, g_fLJSound[0])
+ ON_CVAR_CHANGE_FLOAT(g_hCvarLJSound2, g_fLJSound[1])
+ ON_CVAR_CHANGE_FLOAT(g_hCvarLJSound3, g_fLJSound[2])
+ ON_CVAR_CHANGE_FLOAT(g_hCvarLJSound4, g_fLJSound[3])
+ ON_CVAR_CHANGE_FLOAT(g_hCvarLJSound5, g_fLJSound[4])
+ ON_CVAR_CHANGE_BOOL(g_hCvarLJSoundToAll[0], g_bLJSoundToAll[0])
+ ON_CVAR_CHANGE_BOOL(g_hCvarLJSoundToAll[1], g_bLJSoundToAll[1])
+ ON_CVAR_CHANGE_BOOL(g_hCvarLJSoundToAll[2], g_bLJSoundToAll[2])
+ ON_CVAR_CHANGE_BOOL(g_hCvarLJSoundToAll[3], g_bLJSoundToAll[3])
+ ON_CVAR_CHANGE_BOOL(g_hCvarLJSoundToAll[4], g_bLJSoundToAll[4])
+ else if(hCvar == g_hCvarLJSound1File)
+ {
+ strcopy(g_strLJSoundFile[0], sizeof(g_strLJSoundFile[]), strNewValue);
+ PrecacheSound(g_strLJSoundFile[0]);
+ }
+ else if(hCvar == g_hCvarLJSound2File)
+ {
+ strcopy(g_strLJSoundFile[1], sizeof(g_strLJSoundFile[]), strNewValue);
+ PrecacheSound(g_strLJSoundFile[1]);
+ }
+ else if(hCvar == g_hCvarLJSound3File)
+ {
+ strcopy(g_strLJSoundFile[2], sizeof(g_strLJSoundFile[]), strNewValue);
+ PrecacheSound(g_strLJSoundFile[2]);
+ }
+ else if(hCvar == g_hCvarLJSound4File)
+ {
+ strcopy(g_strLJSoundFile[3], sizeof(g_strLJSoundFile[]), strNewValue);
+ PrecacheSound(g_strLJSoundFile[3]);
+ }
+ else if(hCvar == g_hCvarLJSound5File)
+ {
+ strcopy(g_strLJSoundFile[4], sizeof(g_strLJSoundFile[]), strNewValue);
+ PrecacheSound(g_strLJSoundFile[4]);
+ }
+
+ ON_CVAR_CHANGE_FLOAT(g_hCvarMaxspeed, g_fMaxspeed)
+ ON_CVAR_CHANGE_BOOL(g_hCvarEnableBunnyHopping, g_bEnableBunnyHopping)
+}
+
+#undef ON_CVAR_CHANGE_BOOL
+#undef ON_CVAR_CHANGE_INT
+#undef ON_CVAR_CHANGE_FLOAT
+
+public OnMapStart()
+{
+ g_BeamModel = PrecacheModel("materials/sprites/bluelaser1.vmt");
+
+ for(new i; i < LJSOUND_NUM; i++)
+ {
+ if(g_strLJSoundFile[i][0] != 0)
+ {
+ PrecacheSound(g_strLJSoundFile[i]);
+ }
+ }
+}
+
+public OnClientPutInServer(client)
+{
+ /*
+ #if defined LJSERV
+ g_PlayerStates[client][bLJEnabled] = true;
+ #else
+ g_PlayerStates[client][bLJEnabled] = true;
+ #endif
+ g_PlayerStates[client][bHidePanel] = true;
+ g_PlayerStates[client][bBeam] = false;
+ g_PlayerStates[client][bSound] = true;
+ //#if defined LJSERV
+ //g_PlayerStates[client][bBlockMode] = true;
+ //#else
+ g_PlayerStates[client][bBlockMode] = false;
+ //#endif
+ g_PlayerStates[client][nVerbosity] = g_nVerbosity;
+ */
+ g_PlayerStates[client][bOnGround] = true;
+ g_PlayerStates[client][fBlockDistance] = -1.0;
+ g_PlayerStates[client][IllegalJumpFlags] = IJF_NONE;
+ g_PlayerStates[client][nSpectators] = 0;
+ g_PlayerStates[client][nSpectatorTarget] = -1;
+ /*
+ #if defined LJSERV
+ g_PlayerStates[client][bShowPrestrafeHint] = true;
+ #endif
+ */
+ SDKHook(client, SDKHook_Touch, hkTouch);
+}
+
+public Action:hkTouch(client, other)
+{
+ new Float:vOrigin[3];
+ GetClientAbsOrigin(client, vOrigin);
+
+ if(other == 0 && !(GetEntityFlags(client) & FL_ONGROUND) &&
+ !(g_PlayerStates[client][bBlockMode] && g_PlayerStates[client][bFailedBlock] &&
+ vOrigin[2] - g_PlayerStates[client][vJumpOrigin][2] < HEIGHT_DELTA_MIN(JT_LONGJUMP)))
+ {
+ g_PlayerStates[client][IllegalJumpFlags] |= IJF_WORLD;
+
+ #if defined DEBUG
+ PrintToChat(client, "%d, %d, %f, %d, %d", g_PlayerStates[client][bBlockMode], g_PlayerStates[client][bFailedBlock], vOrigin[2] - g_PlayerStates[client][vJumpOrigin][2],
+ vOrigin[2] - g_PlayerStates[client][vJumpOrigin][2] < HEIGHT_DELTA_MIN(JT_LONGJUMP), GetGameTickCount());
+ #endif
+ }
+ else
+ {
+ decl String:strClassname[64];
+ GetEdictClassname(other, strClassname, sizeof(strClassname));
+
+ if(!strcmp(strClassname, "trigger_push"))
+ {
+ g_PlayerStates[client][IllegalJumpFlags] |= IJF_BOOSTER;
+
+ #if defined DEBUG
+ PrintToChat(client, "booster");
+ #endif
+ }
+ }
+}
+
+public Action:Command_Delete(client, args)
+{
+ SQL_Query(g_DB, "drop table ljtop");
+ SQL_Query(g_DB, "drop table ljtopstrafes");
+
+ return Plugin_Handled;
+}
+
+public Action:Command_LJHelp(client, args)
+{
+ new Handle:hHelpPanel = CreatePanel();
+
+ SetPanelTitle(hHelpPanel, "!lj");
+ DrawPanelText(hHelpPanel, "!ljsettings, !ljs");
+ DrawPanelText(hHelpPanel, "!ljpanel");
+ DrawPanelText(hHelpPanel, "!ljbeam");
+ DrawPanelText(hHelpPanel, "!ljblock");
+ DrawPanelText(hHelpPanel, "!ljsound");
+ DrawPanelText(hHelpPanel, "!gap");
+ DrawPanelText(hHelpPanel, "!blockgap");
+ DrawPanelText(hHelpPanel, "!ljtop");
+
+ SendPanelToClient(hHelpPanel, client, EmptyPanelHandler, 10);
+
+ CloseHandle(hHelpPanel);
+
+ return Plugin_Handled;
+}
+
+public Action:Command_LJ(client, args)
+{
+ g_PlayerStates[client][bLJEnabled] = !g_PlayerStates[client][bLJEnabled];
+ SetCookie(client, g_hCookieLJEnabled, g_PlayerStates[client][bLJEnabled]);
+ PrintToChat(client, "Longjump stats %s", g_PlayerStates[client][bLJEnabled] ? "ENABLED" : "DISABLED");
+
+ return Plugin_Handled;
+}
+
+public Action:Command_LJSettings(client, args)
+{
+ ShowSettingsPanel(client);
+
+ return Plugin_Handled;
+}
+
+public OnClientCookiesCached(client)
+{
+ decl String:strCookie[64];
+
+ GetClientCookie(client, g_hCookieDefaultsSet, strCookie, sizeof(strCookie));
+
+ if(StringToInt(strCookie) == 0)
+ {
+ #if defined LJSERV
+ SetCookie(client, g_hCookieLJEnabled, true);
+ SetCookie(client, g_hCookieBlockMode, true);
+ #endif
+
+ SetCookie(client, g_hCookieSound, g_bLJSound);
+
+ SetCookie(client, g_hCookieShowBhopStats, g_bShowBhopStats);
+
+ SetCookie(client, g_hCookieVerbosity, g_nVerbosity);
+
+ SetCookie(client, g_hCookieShowAllJumps, false);
+
+ #if defined LJSERV
+ SetCookie(client, g_hCookieShowPrestrafeHint, true);
+ #endif
+
+ SetCookie(client, g_hCookieDefaultsSet, true);
+ }
+
+
+ GetClientCookie(client, g_hCookieLJEnabled, strCookie, sizeof(strCookie));
+ g_PlayerStates[client][bLJEnabled] = bool:StringToInt(strCookie);
+
+ GetClientCookie(client, g_hCookieBlockMode, strCookie, sizeof(strCookie));
+ g_PlayerStates[client][bBlockMode] = bool:StringToInt(strCookie);
+
+ GetClientCookie(client, g_hCookieBeam, strCookie, sizeof(strCookie));
+ g_PlayerStates[client][bBeam] = bool:StringToInt(strCookie);
+
+ GetClientCookie(client, g_hCookieSound, strCookie, sizeof(strCookie));
+ g_PlayerStates[client][bSound] = bool:StringToInt(strCookie);
+
+ GetClientCookie(client, g_hCookieHidePanel, strCookie, sizeof(strCookie));
+ g_PlayerStates[client][bHidePanel] = bool:StringToInt(strCookie);
+
+ GetClientCookie(client, g_hCookieHideBhopPanel, strCookie, sizeof(strCookie));
+ g_PlayerStates[client][bHideBhopPanel] = bool:StringToInt(strCookie);
+
+ GetClientCookie(client, g_hCookieShowBhopStats, strCookie, sizeof(strCookie));
+ g_PlayerStates[client][bShowBhopStats] = bool:StringToInt(strCookie);
+
+ GetClientCookie(client, g_hCookieVerbosity, strCookie, sizeof(strCookie));
+ g_PlayerStates[client][nVerbosity] = StringToInt(strCookie);
+
+ GetClientCookie(client, g_hCookieShowAllJumps, strCookie, sizeof(strCookie));
+ g_PlayerStates[client][bShowAllJumps] = bool:StringToInt(strCookie);
+
+ #if defined LJSERV
+ GetClientCookie(client, g_hCookieShowPrestrafeHint, strCookie, sizeof(strCookie));
+ g_PlayerStates[client][bShowPrestrafeHint] = bool:StringToInt(strCookie);
+ #endif
+
+ GetClientCookie(client, g_hCookiePersonalBest, strCookie, sizeof(strCookie));
+ g_PlayerStates[client][fPersonalBest] = StringToFloat(strCookie);
+}
+
+ShowSettingsPanel(client)
+{
+ new Handle:hMenu = CreateMenu(SettingsMenuHandler);
+
+ decl String:buf[64];
+
+ Format(buf, sizeof(buf), "LJ stats: %s", g_PlayerStates[client][bLJEnabled] ? "On" : "Off");
+ AddMenuItem(hMenu, "ljenabled", buf);
+
+ Format(buf, sizeof(buf), "Block mode: %s", g_PlayerStates[client][bBlockMode] ? "On" : "Off");
+ AddMenuItem(hMenu, "block", buf);
+
+ Format(buf, sizeof(buf), "Beam: %s", g_PlayerStates[client][bBeam] ? "On" : "Off");
+ AddMenuItem(hMenu, "beam", buf);
+
+ Format(buf, sizeof(buf), "Sounds: %s", g_PlayerStates[client][bSound] ? "On" : "Off");
+ AddMenuItem(hMenu, "sound", buf);
+
+ Format(buf, sizeof(buf), "Panel: %s", !g_PlayerStates[client][bHidePanel] ? "On" : "Off");
+ AddMenuItem(hMenu, "panel", buf);
+
+ Format(buf, sizeof(buf), "Bhop panel: %s", !g_PlayerStates[client][bHideBhopPanel] ? "On" : "Off");
+ AddMenuItem(hMenu, "bhoppanel", buf);
+
+ Format(buf, sizeof(buf), "Bhop stats: %s", g_PlayerStates[client][bShowBhopStats] ? "On" : "Off");
+ AddMenuItem(hMenu, "bhopstats", buf);
+
+ Format(buf, sizeof(buf), "Verbosity: %d", g_PlayerStates[client][nVerbosity]);
+ AddMenuItem(hMenu, "verbosity", buf);
+
+ Format(buf, sizeof(buf), "Show all jumps: %s", g_PlayerStates[client][bShowAllJumps] ? "On" : "Off");
+ AddMenuItem(hMenu, "showalljumps", buf);
+
+ #if defined LJSERV
+ Format(buf, sizeof(buf), "Prestrafe hint: %s", g_PlayerStates[client][bShowPrestrafeHint] ? "On" : "Off");
+ AddMenuItem(hMenu, "prestrafehint", buf);
+ #endif
+
+ DisplayMenu(hMenu, client, 0);
+}
+
+public SettingsMenuHandler(Handle:hMenu, MenuAction:ma, client, nItem)
+{
+ switch(ma)
+ {
+ case MenuAction_Select:
+ {
+ decl String:strInfo[16];
+
+ if(!GetMenuItem(hMenu, nItem, strInfo, sizeof(strInfo)))
+ {
+ LogError("rip menu...");
+ return;
+ }
+
+ if(!strcmp(strInfo, "ljenabled"))
+ {
+ g_PlayerStates[client][bLJEnabled] = !g_PlayerStates[client][bLJEnabled];
+ SetCookie(client, g_hCookieLJEnabled, g_PlayerStates[client][bLJEnabled]);
+ PrintToChat(client, "LJ stats are now %s", g_PlayerStates[client][bLJEnabled] ? "on" : "off");
+ ShowSettingsPanel(client);
+ }
+ else if(!strcmp(strInfo, "block"))
+ {
+ g_PlayerStates[client][bBlockMode] = !g_PlayerStates[client][bBlockMode];
+ SetCookie(client, g_hCookieBlockMode, g_PlayerStates[client][bBlockMode]);
+ PrintToChat(client, "Block mode is now %s", g_PlayerStates[client][bBlockMode] ? "on" : "off");
+ ShowSettingsPanel(client);
+ }
+ else if(!strcmp(strInfo, "beam"))
+ {
+ g_PlayerStates[client][bBeam] = !g_PlayerStates[client][bBeam];
+ SetCookie(client, g_hCookieBeam, g_PlayerStates[client][bBeam]);
+ PrintToChat(client, "Beam is now %s", g_PlayerStates[client][bBeam] ? "on" : "off");
+ ShowSettingsPanel(client);
+ }
+ else if(!strcmp(strInfo, "sound"))
+ {
+ g_PlayerStates[client][bSound] = !g_PlayerStates[client][bSound];
+ SetCookie(client, g_hCookieSound, g_PlayerStates[client][bSound]);
+ PrintToChat(client, "Sound is now %s", g_PlayerStates[client][bSound] ? "on" : "off");
+ ShowSettingsPanel(client);
+ }
+ else if(!strcmp(strInfo, "panel"))
+ {
+ g_PlayerStates[client][bHidePanel] = !g_PlayerStates[client][bHidePanel];
+ SetCookie(client, g_hCookieHidePanel, g_PlayerStates[client][bHidePanel]);
+ PrintToChat(client, "Panel is now %s", g_PlayerStates[client][bHidePanel] ? "hidden" : "visible");
+ ShowSettingsPanel(client);
+ }
+ else if(!strcmp(strInfo, "bhoppanel"))
+ {
+ g_PlayerStates[client][bHideBhopPanel] = !g_PlayerStates[client][bHideBhopPanel];
+ SetCookie(client, g_hCookieHideBhopPanel, g_PlayerStates[client][bHideBhopPanel]);
+ PrintToChat(client, "Bhop panel is now %s", g_PlayerStates[client][bHideBhopPanel] ? "hidden" : "visible");
+ ShowSettingsPanel(client);
+ }
+ else if(!strcmp(strInfo, "bhopstats"))
+ {
+ g_PlayerStates[client][bShowBhopStats] = !g_PlayerStates[client][bShowBhopStats];
+ SetCookie(client, g_hCookieShowBhopStats, g_PlayerStates[client][bShowBhopStats]);
+ PrintToChat(client, "Bhop stats are now %s", g_PlayerStates[client][bShowBhopStats] ? "on" : "off");
+ ShowSettingsPanel(client);
+ }
+ else if(!strcmp(strInfo, "verbosity"))
+ {
+ hMenu = CreateMenu(VerbosityMenuHandler);
+
+ AddMenuItem(hMenu, "0", "0");
+ AddMenuItem(hMenu, "1", "1");
+ AddMenuItem(hMenu, "2", "2");
+ AddMenuItem(hMenu, "3", "3");
+
+ DisplayMenu(hMenu, client, 0);
+ }
+ else if(!strcmp(strInfo, "showalljumps"))
+ {
+ g_PlayerStates[client][bShowAllJumps] = !g_PlayerStates[client][bShowAllJumps];
+ SetCookie(client, g_hCookieShowAllJumps, g_PlayerStates[client][bShowAllJumps]);
+ PrintToChat(client, "Showing all jumps is now %s", g_PlayerStates[client][bShowAllJumps] ? "on" : "off");
+ ShowSettingsPanel(client);
+ }
+ #if defined LJSERV
+ else if(!strcmp(strInfo, "prestrafehint"))
+ {
+ g_PlayerStates[client][bShowPrestrafeHint] = !g_PlayerStates[client][bShowPrestrafeHint];
+ SetCookie(client, g_hCookieShowPrestrafeHint, g_PlayerStates[client][bShowPrestrafeHint]);
+ PrintToChat(client, "Prestrafe hint is now %s", g_PlayerStates[client][bShowPrestrafeHint] ? "on" : "off");
+ ShowSettingsPanel(client);
+ }
+ #endif
+ }
+
+ case MenuAction_End:
+ {
+ CloseHandle(hMenu);
+ }
+ }
+}
+
+SetCookie(client, Handle:hCookie, n)
+{
+ decl String:strCookie[64];
+
+ IntToString(n, strCookie, sizeof(strCookie));
+
+ SetClientCookie(client, hCookie, strCookie);
+}
+
+SetCookieFloat(client, Handle:hCookie, Float:n)
+{
+ decl String:strCookie[64];
+
+ FloatToString(n, strCookie, sizeof(strCookie));
+
+ SetClientCookie(client, hCookie, strCookie);
+}
+
+public VerbosityMenuHandler(Handle:hMenu, MenuAction:ma, client, nItem)
+{
+ switch(ma)
+ {
+ case MenuAction_Select:
+ {
+ g_PlayerStates[client][nVerbosity] = nItem;
+ SetCookie(client, g_hCookieVerbosity, g_PlayerStates[client][nVerbosity]);
+ PrintToChat(client, "Verbosity level is now %d", g_PlayerStates[client][nVerbosity]);
+
+ ShowSettingsPanel(client);
+ }
+
+ case MenuAction_End:
+ {
+ CloseHandle(hMenu);
+ }
+ }
+}
+
+public Action:Command_LJPanel(client, args)
+{
+ g_PlayerStates[client][bHidePanel] = !g_PlayerStates[client][bHidePanel];
+ SetCookie(client, g_hCookieHidePanel, g_PlayerStates[client][bHidePanel]);
+ PrintToChat(client, "Longjump panel %s", g_PlayerStates[client][bHidePanel] ? "ENABLED" : "DISABLED");
+
+ return Plugin_Handled;
+}
+
+public Action:Command_LJBeam(client, args)
+{
+ g_PlayerStates[client][bBeam] = !g_PlayerStates[client][bBeam];
+ SetCookie(client, g_hCookieBeam, g_PlayerStates[client][bBeam]);
+ PrintToChat(client, "Longjump beam %s", g_PlayerStates[client][bBeam] ? "ENABLED" : "DISABLED");
+
+ return Plugin_Handled;
+}
+
+public Action:Command_LJBlock(client, args)
+{
+ g_PlayerStates[client][bBlockMode] = !g_PlayerStates[client][bBlockMode];
+ SetCookie(client, g_hCookieBlockMode, g_PlayerStates[client][bBlockMode]);
+ PrintToChat(client, "Longjump block mode %s", g_PlayerStates[client][bBlockMode] ? "ENABLED" : "DISABLED");
+
+ return Plugin_Handled;
+}
+
+public Action:Command_LJSound(client, args)
+{
+ g_PlayerStates[client][bSound] = !g_PlayerStates[client][bSound];
+ SetCookie(client, g_hCookieSound, g_PlayerStates[client][bSound]);
+ PrintToChat(client, "Longjump sounds %s", g_PlayerStates[client][bSound] ? "enabled" : "disabled");
+
+ return Plugin_Handled;
+}
+
+public Action:Command_LJVersion(client, args)
+{
+ CPrintToChat(client, "{green}ljstats %s by Miu -w-", LJSTATS_VERSION);
+
+ return Plugin_Handled;
+}
+
+public Action:Command_LJTop(client, args)
+{
+ //SendPanelToClient(g_hLJTopLJPanel, client, EmptyPanelHandler, 10);
+ DisplayMenu(g_hLJTopMainMenu, client, MENU_TIME_FOREVER);
+
+ return Plugin_Handled;
+}
+
+public Action:Command_LJTopDelete(client, args)
+{
+ decl String:buf[32];
+ GetCmdArg(1, buf, sizeof(buf));
+
+ new LJTOP_TABLE:nLJTopTable = LJTOP_TABLE:-1;
+
+ for(new LJTOP_TABLE:i; i < LT_END; i++)
+ {
+ if(!strcmp(g_strLJTopTags[i], buf))
+ {
+ nLJTopTable = i;
+ break;
+ }
+ }
+
+ if(nLJTopTable == LJTOP_TABLE:-1)
+ {
+ PrintToChat(client, "Unrecognized table %s", buf);
+
+ return Plugin_Handled;
+ }
+
+
+ decl String:str[4];
+ GetCmdArg(2, str, sizeof(str));
+ new n = StringToInt(str) - 1;
+
+ if(n < 0 || n > LJTOP_NUM_ENTRIES - 1)
+ {
+ PrintToChat(client, "Invalid entry");
+
+ return Plugin_Handled;
+ }
+
+ PrintToChat(client, "Removing %s's %.2f in table %d (%s)", g_LJTop[nLJTopTable][n][m_strName], g_LJTop[nLJTopTable][n][m_fDistance], nLJTopTable, buf);
+
+ LJTopMoveUp(nLJTopTable, n);
+
+ LJTopSave();
+ LJTopCreateMenu(nLJTopTable);
+
+ return Plugin_Handled;
+}
+
+public Action:Command_Gap(client, args)
+{
+ new Handle:hGapPanel = CreatePanel();
+
+ SetPanelTitle(hGapPanel, "Select point 1");
+
+ SendPanelToClient(hGapPanel, client, EmptyPanelHandler, 10);
+
+ CloseHandle(hGapPanel);
+
+ g_PlayerStates[client][GapSelectionMode] = GSM_GAP;
+
+ return Plugin_Handled;
+}
+
+public Action:Command_BlockGap(client, args)
+{
+ new Handle:hGapPanel = CreatePanel();
+
+ SetPanelTitle(hGapPanel, "Select block");
+
+ SendPanelToClient(hGapPanel, client, EmptyPanelHandler, 10);
+
+ CloseHandle(hGapPanel);
+
+ g_PlayerStates[client][GapSelectionMode] = GSM_BLOCKGAP;
+
+ return Plugin_Handled;
+}
+
+GapSelect(client, buttons)
+{
+ if(!(buttons & IN_ATTACK || buttons & IN_ATTACK2 || buttons & IN_USE) ||
+ g_PlayerStates[client][LastButtons] & IN_ATTACK || g_PlayerStates[client][LastButtons] & IN_ATTACK2 || g_PlayerStates[client][LastButtons] & IN_USE)
+ {
+ return;
+ }
+
+ new Float:vPoint[3], Float:vNormal[3];
+ GetGapPoint(vPoint, vNormal, client);
+
+ switch(g_PlayerStates[client][GapSelectionMode])
+ {
+ case GSM_GAP:
+ {
+ Array_Copy(vPoint, g_PlayerStates[client][vGapPoint1], 3);
+
+ SendPanelMsg(client, "Select point 2");
+
+ g_PlayerStates[client][GapSelectionMode] = GSM_GAPSECOND;
+ }
+
+ case GSM_GAPSECOND:
+ {
+ new Float:vPoint1[3];
+ Array_Copy(g_PlayerStates[client][vGapPoint1], vPoint1, 3);
+
+ new Float:xy = Pow(Pow(vPoint[0] - vPoint1[0], 2.0) + Pow(vPoint[1] - vPoint1[1], 2.0), 0.5);
+
+ SendPanelMsg(client, "distance: %.2f, xy: %.2f, z: %.2f", GetVectorDistance(vPoint, vPoint1), xy, vPoint1[2] - vPoint[2]);
+
+ CreateBeamClient(client, vPoint, vPoint1, 0, 0, 128, 5.0);
+
+ g_PlayerStates[client][GapSelectionMode] = GSM_NONE;
+ }
+
+ case GSM_BLOCKGAP:
+ {
+ new Float:vBlockEnd[3], Float:vOrigin[3];
+ GetClientAbsOrigin(client, vOrigin);
+ GetOppositePoint(vBlockEnd, vPoint, vNormal);
+
+ SendPanelMsg(client, "block: %.2f", GetVectorDistance(vPoint, vBlockEnd));
+
+ CreateBeamClient(client, vPoint, vBlockEnd, 255, 0, 0, 5.0);
+
+ g_PlayerStates[client][GapSelectionMode] = GSM_NONE;
+ }
+
+ }
+}
+
+public Action:Command_Tele(client, args)
+{
+ g_PlayerStates[client][IllegalJumpFlags] |= IJF_TELEPORT;
+
+ return Plugin_Continue;
+}
+
+public Action:Command_PersonalBest(client, args)
+{
+ CPrintToChat(client, "{green}Your longjump record is {default}%.2f{green} units", g_PlayerStates[client][fPersonalBest]);
+
+ return Plugin_Handled;
+}
+
+UpdatePersonalBest(client)
+{
+ if(g_PlayerStates[client][JumpType] != JT_LONGJUMP)
+ {
+ return;
+ }
+
+ if(g_PlayerStates[client][fJumpDistance] > g_PlayerStates[client][fPersonalBest])
+ {
+ g_PlayerStates[client][fPersonalBest] = g_PlayerStates[client][fJumpDistance];
+
+ CPrintToChat(client, "{green}Congratulations, you have a new longjump record with {default}%.2f{green} units!", g_PlayerStates[client][fPersonalBest]);
+
+ SetCookieFloat(client, g_hCookiePersonalBest, g_PlayerStates[client][fPersonalBest]);
+ }
+}
+
+public Action:Command_ResetPersonalBest(client, args)
+{
+ SetCookieFloat(client, g_hCookiePersonalBest, 0.0);
+ g_PlayerStates[client][fPersonalBest] = 0.0;
+
+ return Plugin_Continue;
+}
+
+public Action:Command_LJTopLoadFromFile(client, args)
+{
+ decl String:arg[PLATFORM_MAX_PATH];
+ GetCmdArgString(arg, sizeof(arg));
+ LJTopLoad(arg);
+
+ return Plugin_Handled;
+}
+
+LJTopCreateMainMenu()
+{
+ if(g_hLJTopMainMenu != INVALID_HANDLE)
+ {
+ CloseHandle(g_hLJTopMainMenu);
+ }
+
+ g_hLJTopMainMenu = CreateMenu(LJTopMainMenuHandler);
+
+ for(new LJTOP_TABLE:i; i < LT_END; i++)
+ {
+ AddMenuItem(g_hLJTopMainMenu, g_strLJTopTags[i], g_strLJTopTableName[i]);
+ }
+}
+
+public LJTopMainMenuHandler(Handle:hMenu, MenuAction:ma, client, nItem)
+{
+ switch(ma)
+ {
+ case MenuAction_Select:
+ {
+ decl String:strInfo[16];
+
+ if(!GetMenuItem(hMenu, nItem, strInfo, sizeof(strInfo)))
+ {
+ PrintToChat(client, "rip menu...");
+ return;
+ }
+
+ for(new LJTOP_TABLE:i = LJTOP_TABLE:0; i < LT_END; i++)
+ {
+ if(!strcmp(g_strLJTopTags[i], strInfo))
+ {
+ DisplayMenu(g_hLJTopMenus[i], client, 0);
+
+ break;
+ }
+ }
+ }
+
+ case MenuAction_End:
+ {
+ }
+ }
+}
+
+LJTopCreateMenu(LJTOP_TABLE:nTable)
+{
+ if(g_hLJTopMenus[nTable] != INVALID_HANDLE)
+ {
+ CloseHandle(g_hLJTopMenus[nTable]);
+ }
+
+ g_hLJTopMenus[nTable] = CreateMenu(LJTopRecordMenuHandler);
+
+ decl String:buf[128], String:info[32];
+
+ Format(buf, sizeof(buf), "%s top", g_strLJTopTableName[nTable]);
+
+ SetMenuTitle(g_hLJTopMenus[nTable], buf);
+
+ for(new i; i < LJTOP_NUM_ENTRIES; i++)
+ {
+ if(g_LJTop[nTable][i][m_strName][0] == 0)
+ {
+ break;
+ }
+
+ if(nTable == LT_BLOCKLJ)
+ {
+ FormatEx(buf, sizeof(buf), "%s - %.2f (%.2f: %.2f, %d @ %d%%, %.2f)",
+ g_LJTop[LT_BLOCKLJ][i][m_strName], g_LJTop[LT_BLOCKLJ][i][m_fBlockDistance], g_LJTop[LT_BLOCKLJ][i][m_fDistance],
+ g_LJTop[LT_BLOCKLJ][i][m_fPrestrafe], g_LJTop[LT_BLOCKLJ][i][m_nStrafes], RoundFloat(g_LJTop[LT_BLOCKLJ][i][m_fSync]), g_LJTop[LT_BLOCKLJ][i][m_fMaxSpeed]);
+ }
+ else
+ {
+ FormatEx(buf, sizeof(buf), "%s - %.2f (%.2f, %d @ %d%%, %.2f)",
+ g_LJTop[nTable][i][m_strName], g_LJTop[nTable][i][m_fDistance],
+ g_LJTop[nTable][i][m_fPrestrafe], g_LJTop[nTable][i][m_nStrafes], RoundFloat(g_LJTop[nTable][i][m_fSync]), g_LJTop[nTable][i][m_fMaxSpeed]);
+ }
+
+ FormatEx(info, sizeof(info), "%s;%d", g_strLJTopTags[nTable], i);
+
+ AddMenuItem(g_hLJTopMenus[nTable], info, buf);
+ }
+
+ //SetMenuExitBackButton(g_hLJTopMenus[nTable], true);
+}
+
+public LJTopRecordMenuHandler(Handle:hMenu, MenuAction:ma, client, nItem)
+{
+ switch(ma)
+ {
+ case MenuAction_Select:
+ {
+ decl String:info[16];
+
+ if(!GetMenuItem(hMenu, nItem, info, sizeof(info)))
+ {
+ LogError("rip menu...");
+ return;
+ }
+
+ decl String:split[2][16], String:sTime[128], String:buf[128];
+ ExplodeString(info, ";", split, sizeof(split), sizeof(split[]));
+
+ new iTable = _:GetLJTopTable(split[0]);
+ new iEntry = StringToInt(split[1]);
+
+ if(iTable == -1)
+ {
+ LogError("Unrecognized table %s");
+ return;
+ }
+
+ new Handle:hPanel = CreatePanel();
+
+ FormatTime(sTime, sizeof(sTime), NULL_STRING, g_LJTop[iTable][iEntry][m_nTimestamp]); // "%B %d %Y %T"
+
+ FormatEx(buf, sizeof(buf), "%s's %.2f -- %s\n ", g_LJTop[iTable][iEntry][m_strName], g_LJTop[iTable][iEntry][m_fDistance], sTime);
+
+ SetPanelTitle(hPanel, buf);
+
+ for(new i = 0; i < g_LJTop[iTable][iEntry][m_nStrafes] && i < 16; i++)
+ {
+ decl String:strStrafeKey[3];
+ GetStrafeKey(strStrafeKey, g_LJTop[iTable][iEntry][m_StrafeDir][i]);
+
+ DrawPanelTextF(hPanel, "%d %s %.2f %.2f %.2f %.2f",
+ i + 1,
+ strStrafeKey,
+ g_LJTop[iTable][iEntry][m_fStrafeGain][i], g_LJTop[iTable][iEntry][m_fStrafeLoss][i],
+ float(g_LJTop[iTable][iEntry][m_nStrafeTicks][i]) / g_LJTop[iTable][iEntry][m_nTotalTicks] * 100,
+ g_LJTop[iTable][iEntry][m_fStrafeSync][i]);
+ }
+
+ DrawPanelTextF(hPanel, " %.2f%%", g_LJTop[iTable][iEntry][m_fSync]);
+
+ SendPanelToClient(hPanel, client, RecordPanelHandler, 0);
+
+ CloseHandle(hPanel);
+ }
+
+ case MenuAction_Cancel:
+ {
+ if(nItem == -3)
+ {
+ DisplayMenu(g_hLJTopMainMenu, client, 0);
+ }
+ }
+ }
+}
+
+public RecordPanelHandler(Handle:hMenu, MenuAction:ma, client, nItem)
+{
+ switch(ma)
+ {
+ case MenuAction_Select:
+ {
+ DisplayMenu(g_hLJTopMainMenu, client, 0);
+ }
+ }
+}
+
+LJTopLoad(const String:strPath[])
+{
+ // Load top stats into memory from file
+
+ /*decl String:strPath[PLATFORM_MAX_PATH];
+
+ BuildPath(Path_SM, strPath, PLATFORM_MAX_PATH, LJTOP_DIR);
+
+ if(!DirExists(strPath))
+ {
+ PrintToServer("[LJTop] Dir %s nonexistent", strPath);
+ return;
+ }
+
+ StrCat(strPath, sizeof(strPath), LJTOP_FILE);*/
+
+ new Handle:hFile = OpenFile(strPath, "r");
+
+ if(hFile == INVALID_HANDLE)
+ {
+ LogError("[LJTop] Error opening %s", strPath);
+ return;
+ }
+
+ decl String:strLine[1024]; // omg, so big it is???
+ decl String:strBuffers[LJTOP_MAX_NUM_STATS][64];
+
+ ReadFileLine(hFile, strLine, sizeof(strLine));
+
+ new /*nVersion, */MinStats;
+ if(!strcmp(strLine, "1\n"))
+ {
+ //nVersion = 1;
+ MinStats = LJTOP_MIN_NUM_STATS_1;
+
+ if(IsEndOfFile(hFile))
+ {
+ PrintToServer("[LJTop] EOF");
+ return;
+ }
+
+ ReadFileLine(hFile, strLine, sizeof(strLine));
+ }
+ else
+ {
+ //nVersion = 0;
+ MinStats = LJTOP_MIN_NUM_STATS_0;
+ }
+
+ do
+ {
+ #if defined DEBUG
+ PrintToServer("[LJTop] read %s", strLine);
+ #endif
+
+ static LJTOP_TABLE:nTable = LJTOP_TABLE:-1;
+ static nEntry = 0;
+
+ new bool:bTable;
+
+ for(new LJTOP_TABLE:j; j < LT_END; j++)
+ {
+ decl String:strTag[16];
+ Format(strTag, sizeof(strTag), "%s:\n", g_strLJTopTags[j]);
+ if(!strcmp(strLine, strTag))
+ {
+ PrintToServer("[LJTop] read tag: %s", g_strLJTopTags[j]);
+ nTable = j;
+ nEntry = 0;
+ bTable = true;
+ }
+ }
+
+ if(bTable)
+ {
+ continue;
+ }
+
+ if(nTable == LJTOP_TABLE:-1)
+ {
+ PrintToServer("[LJTop] no table for line %s", strLine);
+ continue;
+ }
+
+ if(nEntry >= LJTOP_NUM_ENTRIES)
+ {
+ PrintToServer("[LJTop] Too many entries for table %d; ignoring line", nTable);
+ continue;
+ }
+
+ new nLength = ExplodeString(strLine, ";", strBuffers, LJTOP_MAX_NUM_STATS, sizeof(strBuffers[]), false);
+
+ if(nLength < MinStats)
+ {
+ PrintToServer("[LJTop] Unexpected entry %d length (expected at least %d, got %d); ignoring line", nEntry + 1, MinStats, nLength);
+ continue;
+ }
+
+ new k;
+ strcopy(g_LJTop[nTable][nEntry][m_strName], 64, strBuffers[k++]);
+ strcopy(g_LJTop[nTable][nEntry][m_strSteamID], 32, strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_fDistance] = StringToFloat(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_fPrestrafe] = StringToFloat(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_nStrafes] = StringToInt(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_fSync] = StringToFloat(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_fMaxSpeed] = StringToFloat(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_nTotalTicks] = StringToInt(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_fHeightDelta] = StringToFloat(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_fSyncedAngle] = StringToFloat(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_fTotalAngle] = StringToFloat(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_fHeightDelta] = StringToFloat(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_fBlockDistance] = StringToFloat(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_fTrajectory] = StringToFloat(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_nTimestamp] = StringToInt(strBuffers[k++]);
+
+ for(new l; l < (nLength - MinStats) / 5 && l < LJTOP_MAX_STRAFES && k < 64 - 5; l++)
+ {
+ g_LJTop[nTable][nEntry][m_StrafeDir][l] = GetStrafeDir(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_fStrafeGain][l] = StringToFloat(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_fStrafeLoss][l] = StringToFloat(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_nStrafeTicks][l] = StringToInt(strBuffers[k++]);
+ g_LJTop[nTable][nEntry][m_fStrafeSync][l] = StringToFloat(strBuffers[k++]);
+ }
+
+ nEntry++;
+
+ #if defined DEBUG
+ PrintToServer("read %s %.2f in table %d", g_LJTop[nTable][nEntry][m_strName], g_LJTop[nTable][nEntry][m_fDistance], nTable);
+ #endif
+ }
+ while(!IsEndOfFile(hFile) && ReadFileLine(hFile, strLine, sizeof(strLine)));
+
+ CloseHandle(hFile);
+}
+
+LJTopSave()
+{
+ DB_SaveLJTop();
+}
+
+/*LJTopSave()
+{
+ // Delete old file and write entirely new one
+
+ decl String:strPath[PLATFORM_MAX_PATH];
+
+ BuildPath(Path_SM, strPath, PLATFORM_MAX_PATH, LJTOP_DIR);
+
+ if(!DirExists(strPath))
+ {
+ CreateDirectory(strPath, 0x3FF); // 0777
+ }
+
+ StrCat(strPath, sizeof(strPath), LJTOP_FILE);
+
+ new Handle:hFile = OpenFile(strPath, "w"); // This will overwrite the old file
+
+ if(hFile == INVALID_HANDLE)
+ {
+ PrintToServer("[LJTop] Error opening %s", strPath);
+ return;
+ }
+
+ WriteFileLine(hFile, "1", false);
+
+ decl String:buf[512], String:buf2[128];
+
+ for(new nIndex; nIndex < _:LT_END; nIndex++)
+ {
+ Format(buf, sizeof(buf), "%s:", g_strLJTopTags[nIndex]);
+ if(!WriteFileLine(hFile, buf, false))
+ {
+ PrintToServer("[LJTop] Error writing to %s", strPath);
+ PrintToChatAll("[LJTop] Error saving ljtop");
+ }
+
+ for(new i; i < LJTOP_NUM_ENTRIES; i++)
+ {
+ if(g_LJTop[nIndex][i][m_strSteamID][0] == 0)
+ {
+ break;
+ }
+
+ Format(buf, sizeof(buf), "%s;%s;%f;%f;%d;%f;%f;%d;%f;%f;%f;%f;%f;%f;%d;",
+ g_LJTop[nIndex][i][m_strName],
+ g_LJTop[nIndex][i][m_strSteamID],
+ g_LJTop[nIndex][i][m_fDistance],
+ g_LJTop[nIndex][i][m_fPrestrafe],
+ g_LJTop[nIndex][i][m_nStrafes],
+
+ g_LJTop[nIndex][i][m_fSync],
+ g_LJTop[nIndex][i][m_fMaxSpeed],
+ g_LJTop[nIndex][i][m_nTotalTicks],
+ g_LJTop[nIndex][i][m_fHeightDelta],
+ g_LJTop[nIndex][i][m_fSyncedAngle],
+
+ g_LJTop[nIndex][i][m_fTotalAngle],
+ g_LJTop[nIndex][i][m_fHeightDelta],
+ g_LJTop[nIndex][i][m_fBlockDistance],
+ g_LJTop[nIndex][i][m_fTrajectory],
+ g_LJTop[nIndex][i][m_nTimestamp]);
+
+ for(new j; j < g_LJTop[nIndex][i][m_nStrafes] && j < LJTOP_MAX_STRAFES; j++)
+ {
+ decl String:strStrafeKey[4];
+ GetStrafeKey(strStrafeKey, g_LJTop[nIndex][i][m_StrafeDir][j]);
+ Format(buf2, sizeof(buf2), "%s;%f;%f;%d;%f;",
+ strStrafeKey,
+ g_LJTop[nIndex][i][m_fStrafeGain][j],
+ g_LJTop[nIndex][i][m_fStrafeLoss][j],
+ g_LJTop[nIndex][i][m_nStrafeTicks][j],
+ g_LJTop[nIndex][i][m_fStrafeSync][j]);
+
+ StrCat(buf, sizeof(buf), buf2);
+ }
+
+ if(!WriteFileLine(hFile, buf))
+ {
+ PrintToServer("[LJTop] Error writing to %s", strPath);
+ PrintToChatAll("[LJTop] Error saving ljtop");
+ }
+ }
+ }
+
+ CloseHandle(hFile);
+}*/
+
+GetStrafeKey(String:str[], STRAFE_DIRECTION:Dir)
+{
+ if(Dir == SD_W)
+ {
+ strcopy(str, 3, "W");
+ }
+ else if(Dir == SD_A)
+ {
+ strcopy(str, 3, "A");
+ }
+ else if(Dir == SD_S)
+ {
+ strcopy(str, 3, "S");
+ }
+ else if(Dir == SD_D)
+ {
+ strcopy(str, 3, "D");
+ }
+ else if(Dir == SD_WA)
+ {
+ strcopy(str, 3, "WA");
+ }
+ else if(Dir == SD_WD)
+ {
+ strcopy(str, 3, "WD");
+ }
+ else if(Dir == SD_SA)
+ {
+ strcopy(str, 3, "SA");
+ }
+ else if(Dir == SD_SD)
+ {
+ strcopy(str, 3, "SD");
+ }
+}
+
+STRAFE_DIRECTION:GetStrafeDir(String:str[])
+{
+ if(!strcmp(str, "W"))
+ {
+ return SD_W;
+ }
+ else if(!strcmp(str, "A"))
+ {
+ return SD_A;
+ }
+ else if(!strcmp(str, "S"))
+ {
+ return SD_S;
+ }
+ else if(!strcmp(str, "D"))
+ {
+ return SD_D;
+ }
+ else if(!strcmp(str, "WA"))
+ {
+ return SD_WA;
+ }
+ else if(!strcmp(str, "WD"))
+ {
+ return SD_WD;
+ }
+ else if(!strcmp(str, "SA"))
+ {
+ return SD_SA;
+ }
+ else if(!strcmp(str, "SD"))
+ {
+ return SD_SD;
+ }
+
+ return SD_NONE;
+}
+
+LJTopMoveDown(LJTOP_TABLE:nIndex, nOldPos, nPos)
+{
+ // move entries down for insertion
+ for(new i = nOldPos - 1; i >= nPos; i--)
+ {
+ strcopy(g_LJTop[nIndex][i + 1][m_strName], 64, g_LJTop[nIndex][i][m_strName]);
+ strcopy(g_LJTop[nIndex][i + 1][m_strSteamID], 32, g_LJTop[nIndex][i][m_strSteamID]);
+ g_LJTop[nIndex][i + 1][m_fDistance] = g_LJTop[nIndex][i][m_fDistance];
+ g_LJTop[nIndex][i + 1][m_fPrestrafe] = g_LJTop[nIndex][i][m_fPrestrafe];
+ g_LJTop[nIndex][i + 1][m_nStrafes] = g_LJTop[nIndex][i][m_nStrafes];
+ g_LJTop[nIndex][i + 1][m_fSync] = g_LJTop[nIndex][i][m_fSync];
+ g_LJTop[nIndex][i + 1][m_fMaxSpeed] = g_LJTop[nIndex][i][m_fMaxSpeed];
+ g_LJTop[nIndex][i + 1][m_nTotalTicks] = g_LJTop[nIndex][i][m_nTotalTicks];
+ g_LJTop[nIndex][i + 1][m_fSyncedAngle] = g_LJTop[nIndex][i][m_fSyncedAngle];
+ g_LJTop[nIndex][i + 1][m_fTotalAngle] = g_LJTop[nIndex][i][m_fTotalAngle];
+ g_LJTop[nIndex][i + 1][m_fHeightDelta] = g_LJTop[nIndex][i][m_fHeightDelta];
+ g_LJTop[nIndex][i + 1][m_fBlockDistance] = g_LJTop[nIndex][i][m_fBlockDistance];
+ g_LJTop[nIndex][i + 1][m_fTrajectory] = g_LJTop[nIndex][i][m_fTrajectory];
+ g_LJTop[nIndex][i + 1][m_nTimestamp] = g_LJTop[nIndex][i][m_nTimestamp];
+
+ for(new j; j < g_LJTop[nIndex][i][m_nStrafes]; j++)
+ {
+ g_LJTop[nIndex][i + 1][m_StrafeDir][j] = g_LJTop[nIndex][i][m_StrafeDir][j];
+ g_LJTop[nIndex][i + 1][m_fStrafeGain][j] = g_LJTop[nIndex][i][m_fStrafeGain][j];
+ g_LJTop[nIndex][i + 1][m_fStrafeLoss][j] = g_LJTop[nIndex][i][m_fStrafeLoss][j];
+ g_LJTop[nIndex][i + 1][m_nStrafeTicks][j] = g_LJTop[nIndex][i][m_nStrafeTicks][j];
+ g_LJTop[nIndex][i + 1][m_fStrafeSync][j] = g_LJTop[nIndex][i][m_fStrafeSync][j];
+ }
+ }
+}
+
+LJTopMoveUp(LJTOP_TABLE:nIndex, nPos)
+{
+ for(new i = nPos; i < 9; i++)
+ {
+ strcopy(g_LJTop[nIndex][i][m_strName], 64, g_LJTop[nIndex][i + 1][m_strName]);
+ strcopy(g_LJTop[nIndex][i][m_strSteamID], 32, g_LJTop[nIndex][i + 1][m_strSteamID]);
+ g_LJTop[nIndex][i][m_fDistance] = g_LJTop[nIndex][i + 1][m_fDistance];
+ g_LJTop[nIndex][i][m_fPrestrafe] = g_LJTop[nIndex][i + 1][m_fPrestrafe];
+ g_LJTop[nIndex][i][m_nStrafes] = g_LJTop[nIndex][i + 1][m_nStrafes];
+ g_LJTop[nIndex][i][m_fSync] = g_LJTop[nIndex][i + 1][m_fSync];
+ g_LJTop[nIndex][i][m_fMaxSpeed] = g_LJTop[nIndex][i + 1][m_fMaxSpeed];
+ g_LJTop[nIndex][i][m_nTotalTicks] = g_LJTop[nIndex][i + 1][m_nTotalTicks];
+ g_LJTop[nIndex][i][m_fSyncedAngle] = g_LJTop[nIndex][i + 1][m_fSyncedAngle];
+ g_LJTop[nIndex][i][m_fTotalAngle] = g_LJTop[nIndex][i + 1][m_fTotalAngle];
+ g_LJTop[nIndex][i][m_fHeightDelta] = g_LJTop[nIndex][i + 1][m_fHeightDelta];
+ g_LJTop[nIndex][i][m_fBlockDistance] = g_LJTop[nIndex][i + 1][m_fBlockDistance];
+ g_LJTop[nIndex][i][m_fTrajectory] = g_LJTop[nIndex][i + 1][m_fTrajectory];
+ g_LJTop[nIndex][i][m_nTimestamp] = g_LJTop[nIndex][i + 1][m_nTimestamp];
+
+ for(new j; j < g_LJTop[nIndex][i + 1][m_nStrafes]; j++)
+ {
+ g_LJTop[nIndex][i][m_StrafeDir][j] = g_LJTop[nIndex][i + 1][m_StrafeDir][j];
+ g_LJTop[nIndex][i][m_fStrafeGain][j] = g_LJTop[nIndex][i + 1][m_fStrafeGain][j];
+ g_LJTop[nIndex][i][m_fStrafeLoss][j] = g_LJTop[nIndex][i + 1][m_fStrafeLoss][j];
+ g_LJTop[nIndex][i][m_nStrafeTicks][j] = g_LJTop[nIndex][i + 1][m_nStrafeTicks][j];
+ g_LJTop[nIndex][i][m_fStrafeSync][j] = g_LJTop[nIndex][i + 1][m_fStrafeSync][j];
+ }
+ }
+
+ // Clear last entry to prevent duplicates
+ strcopy(g_LJTop[nIndex][9][m_strName], 64, "");
+ strcopy(g_LJTop[nIndex][9][m_strSteamID], 32, "");
+ g_LJTop[nIndex][9][m_fDistance] = 0.0;
+ g_LJTop[nIndex][9][m_fPrestrafe] = 0.0;
+ g_LJTop[nIndex][9][m_nStrafes] = 0;
+ g_LJTop[nIndex][9][m_fSync] = 0.0;
+ g_LJTop[nIndex][9][m_fMaxSpeed] = 0.0;
+ g_LJTop[nIndex][9][m_nTotalTicks] = 0;
+ g_LJTop[nIndex][9][m_fSyncedAngle] = 0.0;
+ g_LJTop[nIndex][9][m_fTotalAngle] = 0.0;
+ g_LJTop[nIndex][9][m_fHeightDelta] = 0.0;
+ g_LJTop[nIndex][9][m_fBlockDistance] = 0.0;
+ g_LJTop[nIndex][9][m_nTimestamp] = 0;
+
+ for(new j; j < g_LJTop[nIndex][9][m_nStrafes]; j++)
+ {
+ g_LJTop[nIndex][9][m_StrafeDir][j] = SD_NONE;
+ g_LJTop[nIndex][9][m_fStrafeGain][j] = 0.0;
+ g_LJTop[nIndex][9][m_fStrafeLoss][j] = 0.0;
+ g_LJTop[nIndex][9][m_nStrafeTicks][j] = 0;
+ g_LJTop[nIndex][9][m_fStrafeSync][j] = 0.0;
+ }
+}
+
+LJTopUpdate(client)
+{
+ if(g_PlayerStates[client][JumpType] == JT_LONGJUMP)
+ {
+ if(g_PlayerStates[client][fJumpDistance] > g_LJTop[LT_LJ][LJTOP_NUM_ENTRIES - 1][m_fDistance])
+ {
+ LJTopUpdateTable(client, LT_LJ);
+ }
+ if(g_PlayerStates[client][bBlockMode] && !g_PlayerStates[client][bFailedBlock] && g_PlayerStates[client][fBlockDistance] > g_LJTop[LT_BLOCKLJ][LJTOP_NUM_ENTRIES - 1][m_fBlockDistance])
+ {
+ LJTopUpdateTable(client, LT_BLOCKLJ);
+ }
+ if(g_PlayerStates[client][JumpDir] == JD_SIDEWAYS && g_PlayerStates[client][fJumpDistance] > g_LJTop[LT_SWLJ][LJTOP_NUM_ENTRIES - 1][m_fDistance])
+ {
+ LJTopUpdateTable(client, LT_SWLJ);
+ }
+ if(g_PlayerStates[client][JumpDir] == JD_BACKWARDS && g_PlayerStates[client][fJumpDistance] > g_LJTop[LT_BWLJ][LJTOP_NUM_ENTRIES - 1][m_fDistance])
+ {
+ LJTopUpdateTable(client, LT_BWLJ);
+ }
+ }
+ else if(g_PlayerStates[client][JumpType] == JT_COUNTJUMP && g_PlayerStates[client][fJumpDistance] > g_LJTop[LT_CJ][LJTOP_NUM_ENTRIES - 1][m_fDistance])
+ {
+ LJTopUpdateTable(client, LT_CJ);
+ }
+ else if(g_PlayerStates[client][JumpType] == JT_BHOPJUMP && g_PlayerStates[client][fJumpDistance] > g_LJTop[LT_BJ][LJTOP_NUM_ENTRIES - 1][m_fDistance] && (!g_PlayerStates[client][bStamina] || g_bLJTopAllowEasyBJ)) // There's no such thing as an easy bj, only sore jaws, pubes down your throat and the taste of acidic ejaculate
+ {
+ LJTopUpdateTable(client, LT_BJ);
+ }
+ else if(g_PlayerStates[client][JumpType] == JT_LADDERJUMP && g_PlayerStates[client][fJumpDistance] > g_LJTop[LT_LAJ][LJTOP_NUM_ENTRIES - 1][m_fDistance])
+ {
+ LJTopUpdateTable(client, LT_LAJ);
+ }
+ else if(g_PlayerStates[client][JumpType] == JT_BHOP && !g_bEnableBunnyHopping && g_PlayerStates[client][fJumpDistance] > g_LJTop[LT_STRAFEBHOP][LJTOP_NUM_ENTRIES - 1][m_fDistance])
+ {
+ LJTopUpdateTable(client, LT_STRAFEBHOP);
+ }
+}
+
+LJTopUpdateTable(client, LJTOP_TABLE:nLJTopTable)
+{
+ decl String:strName[64], String:strSteamID[32];
+ GetClientName(client, strName, sizeof(strName));
+ GetClientAuthString(client, strSteamID, sizeof(strSteamID));
+
+ decl nIndex;
+ while((nIndex = FindCharInString(strName, ';')) != -1)
+ {
+ strName[nIndex] = '-';
+ }
+
+ new nPos = 0;
+
+ while(nPos < 9 &&
+ (nLJTopTable == LT_BLOCKLJ ? g_PlayerStates[client][fBlockDistance] < g_LJTop[nLJTopTable][nPos][m_fBlockDistance] ||
+ (g_PlayerStates[client][fBlockDistance] == g_LJTop[nLJTopTable][nPos][m_fBlockDistance] &&
+ g_PlayerStates[client][fJumpDistance] < g_LJTop[nLJTopTable][nPos][m_fDistance]) :
+ g_PlayerStates[client][fJumpDistance] < g_LJTop[nLJTopTable][nPos][m_fDistance])) // longest statement in history
+ {
+ if(!strcmp(g_LJTop[nLJTopTable][nPos][m_strSteamID], strSteamID))
+ {
+ // player already has better record
+ g_LJTop[nLJTopTable][nPos][m_strName] = strName; // update name
+ return;
+ }
+
+ nPos++;
+ }
+
+ new nOldPos = -1;
+
+ for(new i = 0; i < 10; i++)
+ {
+ if(!strcmp(g_LJTop[nLJTopTable][i][m_strSteamID], strSteamID))
+ {
+ nOldPos = i;
+ break;
+ }
+ }
+
+ new bool:bSilent;
+
+ if(/*g_LJTop[nLJTopTable][nPos][m_strSteamID][0] == 0 || */g_PlayerStates[client][fJumpDistance] < g_fLJMin ||
+ (nLJTopTable == LT_BLOCKLJ && nOldPos == nPos && g_PlayerStates[client][fBlockDistance] == g_LJTop[nLJTopTable][nPos][m_fBlockDistance]))
+ {
+ bSilent = true;
+ }
+
+ /*
+ enum TopStats
+ {
+ String:m_strName[64 / 4],
+ String:m_strSteamID[32 / 4],
+ Float:m_fDistance,
+ Float:m_fPrestrafe,
+ m_nStrafes,
+ Float:m_fSync,
+ Float:m_fMaxSpeed,
+ m_nTotalTicks,
+ Float:m_fSyncedAngle,
+ Float:m_fTotalAngle,
+ Float:m_fHeightDelta,
+ Float:m_fBlockDistance,
+ Float:m_fTrajectory,
+ m_nTimestamp,
+
+ m_StrafeDir[LJTOP_MAX_STRAFES],
+ Float:m_fStrafeGain[LJTOP_MAX_STRAFES],
+ Float:m_fStrafeLoss[LJTOP_MAX_STRAFES],
+ m_nStrafeTicks[LJTOP_MAX_STRAFES],
+ Float:m_fStrafeSync[LJTOP_MAX_STRAFES],
+ }
+ */
+
+ LJTopMoveDown(nLJTopTable, nOldPos == -1 ? 9 : nOldPos, nPos);
+
+ // overwrite entry
+ strcopy(g_LJTop[nLJTopTable][nPos][m_strName], 64, strName);
+ strcopy(g_LJTop[nLJTopTable][nPos][m_strSteamID], 32, strSteamID);
+ g_LJTop[nLJTopTable][nPos][m_fDistance] = g_PlayerStates[client][fJumpDistance];
+ g_LJTop[nLJTopTable][nPos][m_fPrestrafe] = g_PlayerStates[client][fPrestrafe];
+ g_LJTop[nLJTopTable][nPos][m_nStrafes] = g_PlayerStates[client][nStrafes];
+ g_LJTop[nLJTopTable][nPos][m_fSync] = g_PlayerStates[client][fSync];
+ g_LJTop[nLJTopTable][nPos][m_fMaxSpeed] = g_PlayerStates[client][fMaxSpeed];
+ g_LJTop[nLJTopTable][nPos][m_nTotalTicks] = g_PlayerStates[client][nTotalTicks];
+ g_LJTop[nLJTopTable][nPos][m_fSyncedAngle] = g_PlayerStates[client][fSyncedAngle];
+ g_LJTop[nLJTopTable][nPos][m_fTotalAngle] = g_PlayerStates[client][fTotalAngle];
+ g_LJTop[nLJTopTable][nPos][m_fHeightDelta] = g_PlayerStates[client][fHeightDelta];
+ g_LJTop[nLJTopTable][nPos][m_fBlockDistance] = g_PlayerStates[client][fBlockDistance];
+ g_LJTop[nLJTopTable][nPos][m_fTrajectory] = g_PlayerStates[client][fTrajectory];
+ g_LJTop[nLJTopTable][nPos][m_nTimestamp] = GetTime();
+
+ for(new j; j < g_PlayerStates[client][nStrafes]; j++)
+ {
+ g_LJTop[nLJTopTable][nPos][m_StrafeDir][j] = g_PlayerStates[client][StrafeDir][j];
+ g_LJTop[nLJTopTable][nPos][m_fStrafeGain][j] = g_PlayerStates[client][fStrafeGain][j];
+ g_LJTop[nLJTopTable][nPos][m_fStrafeLoss][j] = g_PlayerStates[client][fStrafeLoss][j];
+ g_LJTop[nLJTopTable][nPos][m_nStrafeTicks][j] = g_PlayerStates[client][nStrafeTicks][j];
+ g_LJTop[nLJTopTable][nPos][m_fStrafeSync][j] = g_PlayerStates[client][fStrafeSync][j];
+ }
+
+ LJTopSave();
+ LJTopCreateMenu(nLJTopTable);
+
+ if(bSilent)
+ {
+ return;
+ }
+
+ if(nLJTopTable == LT_BLOCKLJ)
+ {
+ CPrintToChatAll("%s {green}%s top {default}%d{green} in block lj top with {default}%.2f{green} longjump at {default}%.1f{green} block!",
+ strName, nPos == nOldPos ? "has improved their" : "is now", nPos + 1, g_PlayerStates[client][fJumpDistance], g_PlayerStates[client][fBlockDistance]);
+ }
+ else
+ {
+ CPrintToChatAll("%s {green}%s top {default}%d{green} in %s top with {default}%.2f{green} %s!",
+ strName, nPos == nOldPos ? "has improved their" : "is now", nPos + 1, g_strLJTopOutput[nLJTopTable], g_PlayerStates[client][fJumpDistance], g_strJumpTypeLwr[g_PlayerStates[client][JumpType]]);
+ }
+}
+
+public Native_CancelJump(Handle:hPlugin, nParams)
+{
+ CancelJump(GetNativeCell(1));
+}
+
+CancelJump(client)
+{
+ g_PlayerStates[client][bOnGround] = true;
+}
+
+public Action:Event_PlayerJump(Handle:event, const String:name[], bool:dontBroadcast)
+{
+ new client = GetClientOfUserId(GetEventInt(event, "userid"));
+
+ PlayerJump(client);
+}
+
+public Action:Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast) {
+ new id = GetEventInt(event, "userid");
+ g_PlayerStates[id][IllegalJumpFlags] = IJF_NOCLIP;
+}
+
+// cba with another enum so JT_LONGJUMP = jump, JT_DROP = slide off edge, JT_LADDERJUMP = ladder
+PlayerJump(client, JUMP_TYPE:JumpType2 = JT_LONGJUMP)
+{
+ g_PlayerStates[client][bOnGround] = false;
+
+ new Float:fTime = GetGameTime();
+ if(fTime - g_PlayerStates[client][fLandTime] < BHOP_TIME)//if((g_PlayerStates[client][nLastAerialTick] - GetGameTickCount()) * GetTickInterval() < BHOP_TIME)
+ {
+ g_PlayerStates[client][nBhops]++;
+ }
+ else
+ {
+ g_PlayerStates[client][nBhops] = 0;
+
+ // Only reset flags when jump chain stops so that players can't e.g. boost in the first jump and get a high distance on the next in a bhopjump
+ g_PlayerStates[client][IllegalJumpFlags] = IJF_NONE;
+ }
+
+ g_PlayerStates[client][fLastJumpHeightDelta] = g_PlayerStates[client][fHeightDelta];
+
+ for(new i = 0; i < g_PlayerStates[client][nStrafes] && i < MAX_STRAFES; i++)
+ {
+ g_PlayerStates[client][fStrafeGain][i] = 0.0;
+ g_PlayerStates[client][fStrafeLoss][i] = 0.0;
+ g_PlayerStates[client][fStrafeSync][i] = 0.0;
+ g_PlayerStates[client][nStrafeTicks][i] = 0;
+ g_PlayerStates[client][nStrafeTicksSynced][i] = 0;
+ }
+
+ // Reset stuff
+ g_PlayerStates[client][JumpDir] = JD_NONE;
+ g_PlayerStates[client][CurStrafeDir] = SD_NONE;
+ g_PlayerStates[client][nStrafes] = 0;
+ g_PlayerStates[client][fSync] = 0.0;
+ g_PlayerStates[client][fMaxSpeed] = 0.0;
+ g_PlayerStates[client][fJumpHeight] = 0.0;
+ g_PlayerStates[client][nTotalTicks] = 0;
+ g_PlayerStates[client][fTotalAngle] = 0.0;
+ g_PlayerStates[client][fSyncedAngle] = 0.0;
+ g_PlayerStates[client][fEdge] = -1.0;
+ g_PlayerStates[client][fBlockDistance] = -1.0;
+ g_PlayerStates[client][bStamina] = !GetEntPropFloat(client, Prop_Send, "m_flStamina");
+ g_PlayerStates[client][bFailedBlock] = false;
+ g_PlayerStates[client][fTrajectory] = 0.0;
+ g_PlayerStates[client][fGain] = 0.0;
+ g_PlayerStates[client][fLoss] = 0.0;
+ g_PlayerStates[client][nJumpTick] = GetGameTickCount();
+
+ if(JumpType2 == JT_LONGJUMP && g_PlayerStates[client][bBlockMode])
+ {
+ g_PlayerStates[client][fBlockDistance] = GetBlockDistance(client);
+ }
+
+
+ g_PlayerStates[client][LastJumpType] = g_PlayerStates[client][JumpType];
+
+ // Determine jump type
+ if(JumpType2 == JT_DROP || JumpType2 == JT_LADDERJUMP)
+ {
+ g_PlayerStates[client][JumpType] = JumpType2;
+ }
+ else
+ {
+ if(g_PlayerStates[client][nBhops] > 1)
+ {
+ g_PlayerStates[client][JumpType] = JT_BHOP;
+ }
+ else if(g_PlayerStates[client][nBhops] == 1)
+ {
+ if(g_PlayerStates[client][LastJumpType] == JT_DROP)
+ {
+ g_PlayerStates[client][fWJDropPre] = g_PlayerStates[client][fPrestrafe];
+ g_PlayerStates[client][JumpType] = JT_WEIRDJUMP;
+ }
+ else if(g_PlayerStates[client][fLastJumpHeightDelta] > HEIGHT_DELTA_MIN(JT_LONGJUMP))
+ {
+ g_PlayerStates[client][JumpType] = JT_BHOPJUMP;
+ }
+ else
+ {
+ g_PlayerStates[client][JumpType] = JT_BHOP;
+ }
+ }
+ else
+ {
+ if(GetEntProp(client, Prop_Send, "m_bDucking", 1))
+ {
+ g_PlayerStates[client][JumpType] = JT_COUNTJUMP;
+ }
+ else
+ {
+ g_PlayerStates[client][JumpType] = JT_LONGJUMP;
+ }
+ }
+ }
+
+ // Jumpoff origin
+ new Float:vOrigin[3];
+ GetClientAbsOrigin(client, vOrigin);
+ Array_Copy(vOrigin, g_PlayerStates[client][vJumpOrigin], 3);
+
+ // Prestrafe
+ g_PlayerStates[client][fPrestrafe] = GetSpeed(client);
+
+ if(g_PlayerStates[client][JumpType] == JT_LONGJUMP || g_PlayerStates[client][JumpType] == JT_COUNTJUMP)
+ {
+ if(g_PlayerStates[client][fPrestrafe] > g_fLJMaxPrestrafe)
+ {
+ g_PlayerStates[client][IllegalJumpFlags] |= IJF_PRESTRAFE;
+ }
+
+ if(!g_bLJScoutStats && (g_fMaxspeed > 250.0 && GetEntPropFloat(client, Prop_Data, "m_flMaxspeed") > 250.0))
+ {
+ new String:strPlayerWeapon[32];
+ GetClientWeapon(client, strPlayerWeapon, sizeof(strPlayerWeapon));
+
+ if(!strcmp(strPlayerWeapon, "weapon_scout") || strPlayerWeapon[0] == 0)
+ {
+ g_PlayerStates[client][IllegalJumpFlags] |= IJF_SCOUT;
+ }
+ }
+ }
+
+ if(JumpType2 == JT_LONGJUMP || g_PlayerStates[client][JumpType] == JT_COUNTJUMP)
+ {
+ g_PlayerStates[client][fEdge] = GetEdge(client);
+ }
+
+ if(g_PlayerStates[client][bLJEnabled] && g_PlayerStates[client][bBeam])
+ {
+ StopBeam(client);
+
+ g_PlayerStates[client][bBeam] = true;
+ }
+}
+
+StopBeam(client)
+{
+ g_PlayerStates[client][bBeam] = false;
+}
+
+GetJumpDistance(client)
+{
+ new Float:vCurOrigin[3];
+ GetClientAbsOrigin(client, vCurOrigin);
+
+ g_PlayerStates[client][fHeightDelta] = vCurOrigin[2] - g_PlayerStates[client][vJumpOrigin][2];
+
+ vCurOrigin[2] = 0.0;
+
+ new Float:v[3];
+ Array_Copy(g_PlayerStates[client][vJumpOrigin], v, 3);
+
+ v[2] = 0.0;
+
+ if(g_PlayerStates[client][JumpType] == JT_LADDERJUMP)
+ {
+ g_PlayerStates[client][fJumpDistance] = GetVectorDistance(v, vCurOrigin);
+ }
+ else
+ {
+ g_PlayerStates[client][fJumpDistance] = GetVectorDistance(v, vCurOrigin) + 32;
+ }
+
+ g_PlayerStates[client][bDuck] = bool:GetEntProp(client, Prop_Send, "m_bDucked", 1);
+ //g_PlayerStates[client][nTotalTicks] = GetGameTickCount() - g_PlayerStates[client][nJumpTick];
+}
+
+GetJumpDistanceLastTick(client)
+{
+ new Float:vCurOrigin[3];
+ Array_Copy(g_PlayerStates[client][vLastOrigin], vCurOrigin, 3);
+
+ g_PlayerStates[client][fHeightDelta] = vCurOrigin[2] - g_PlayerStates[client][vJumpOrigin][2];
+
+ vCurOrigin[2] = 0.0;
+
+ new Float:v[3];
+ Array_Copy(g_PlayerStates[client][vJumpOrigin], v, 3);
+
+ v[2] = 0.0;
+
+ g_PlayerStates[client][fJumpDistance] = GetVectorDistance(v, vCurOrigin) + 32.0;
+
+ g_PlayerStates[client][bDuck] = g_PlayerStates[client][bSecondLastDuckState];
+ //g_PlayerStates[client][nTotalTicks] = GetGameTickCount() - g_PlayerStates[client][nJumpTick];
+ //g_PlayerStates[client][nTotalTicks] -= 1;
+}
+
+CheckValidJump(client)
+{
+ new Float:vOrigin[3];
+ GetClientAbsOrigin(client, vOrigin);
+
+ // Check gravity
+ new Float:fGravity = GetEntPropFloat(client, Prop_Data, "m_flGravity");
+ if(fGravity != 1.0 && fGravity != 0.0)
+ {
+ g_PlayerStates[client][IllegalJumpFlags] |= IJF_GRAVITY;
+ }
+
+ // Check speed
+ if(GetEntPropFloat(client, Prop_Data, "m_flLaggedMovementValue") != 1.0)
+ {
+ g_PlayerStates[client][IllegalJumpFlags] |= IJF_LAGGEDMOVEMENTVALUE;
+ }
+
+ if(GetEntityMoveType(client) & MOVETYPE_NOCLIP)
+ {
+ g_PlayerStates[client][IllegalJumpFlags] |= IJF_NOCLIP;
+ }
+
+
+ // Teleport check
+ new Float:vLastOrig[3], Float:vLastVel[3], Float:vVel[3];
+ Array_Copy(g_PlayerStates[client][vLastOrigin], vLastOrig, 3);
+ Array_Copy(g_PlayerStates[client][vLastVelocity], vLastVel, 3);
+ GetEntPropVector(client, Prop_Data, "m_vecVelocity", vVel);
+
+ vLastOrig[2] = 0.0;
+ vOrigin[2] = 0.0;
+ vLastVel[2] = 0.0;
+ vVel[2] = 0.0;
+
+ // If the player moved further than their last velocity, they teleported
+ // It's slightly off, so adjust velocity
+ // pretty suk // less suk
+ /*
+ teleported 2.461413, 2.461400
+ teleported 2.468606, 2.468604
+ teleported 2.488778, 2.488739
+ teleported 2.517628, 2.517453
+ teleported 2.534332, 2.534170
+ teleported 2.550610, 2.550508
+ teleported 2.567417, 2.567395
+ teleported 2.598604, 2.598514
+ teleported 2.612708, 2.612616
+ teleported 2.633581, 2.633533
+ teleported 2.634170, 2.634044
+ teleported 2.646703, 2.646473
+ teleported 2.657407, 2.657327
+ teleported 2.669471, 2.669248
+ teleported 2.710047, 2.709968
+ teleported 2.723108, 2.722937
+ teleported 2.742104, 2.742006
+ teleported 2.744069, 2.743859
+ teleported 2.751010, 2.750807
+ teleported 2.759773, 2.759721
+ teleported 2.771660, 2.771600
+ teleported 2.822698, 2.822640
+ teleported 2.839976, 2.839771
+ teleported 2.839976, 2.839771
+ teleported 2.850264, 2.850194
+ teleported 2.882310, 2.882229
+ teleported 2.894205, 2.894115
+ teleported 2.905041, 2.905009
+ teleported 2.920642, 2.920416
+ */
+ if(GetVectorDistance(vLastOrig, vOrigin) > GetVectorLength(vVel) / (1.0 / GetTickInterval()) + 0.001)
+ {
+ #if defined DEBUG
+ PrintToChat(client, "teleported %f, %f (%f)", GetVectorDistance(vLastOrig, vOrigin), GetVectorLength(vVel) / (1.0 / GetTickInterval()) + 0.001, GetVectorLength(vLastVel) / (1.0 / GetTickInterval()));
+ #endif
+
+ if(g_PlayerStates[client][bBlockMode])
+ {
+ if(g_PlayerStates[client][bFailedBlock])
+ {
+ #if defined DEBUG
+ PrintToChat(client, "failedblock; returning");
+ #endif
+
+ return;
+ }
+ else
+ {
+ #if defined DEBUG
+ PrintToChat(client, "failedblocklongjump 3 tp %s %f %f %d",
+ g_PlayerStates[client][vLastOrigin][2] >= g_PlayerStates[client][vJumpOrigin][2] + HEIGHT_DELTA_MIN(JT_LONGJUMP) ? "saved" : "not saved",
+ g_PlayerStates[client][vLastOrigin][2], g_PlayerStates[client][vJumpOrigin][2] + HEIGHT_DELTA_MIN(JT_LONGJUMP), GetGameTickCount());
+ #endif
+
+ if(g_PlayerStates[client][vLastOrigin][2] >= g_PlayerStates[client][vJumpOrigin][2] + HEIGHT_DELTA_MIN(JT_LONGJUMP))
+ {
+ GetJumpDistanceLastTick(client);
+ g_PlayerStates[client][bFailedBlock] = true;
+
+ return;
+ }
+ }
+ }
+
+ g_PlayerStates[client][IllegalJumpFlags] |= IJF_TELEPORT;
+ }
+}
+
+TBAnglesToUV(Float:vOut[3], const Float:vAngles[3])
+{
+ vOut[0] = Cosine(vAngles[1] * FLOAT_PI / 180.0) * Cosine(vAngles[0] * FLOAT_PI / 180.0);
+ vOut[1] = Sine(vAngles[1] * FLOAT_PI / 180.0) * Cosine(vAngles[0] * FLOAT_PI / 180.0);
+ vOut[2] = -Sine(vAngles[0] * FLOAT_PI / 180.0);
+}
+
+_OnPlayerRunCmd(client, buttons, const Float:vOrigin[3], const Float:vAngles[3], const Float:vVelocity[3], bool:bDucked, bool:bGround)
+{
+ if(g_PlayerStates[client][GapSelectionMode] != GSM_NONE)
+ {
+ GapSelect(client, buttons);
+ }
+
+ // Manage spectators
+ if(IsClientObserver(client))
+ {
+ if(g_PlayerStates[client][bLJEnabled])
+ {
+ new nObserverMode = GetEntProp(client, Prop_Send, "m_iObserverMode");
+
+ if(nObserverMode == 4 || nObserverMode == 3)
+ {
+ new nTarget = GetEntPropEnt(client, Prop_Send, "m_hObserverTarget");
+
+ if(g_PlayerStates[client][nSpectatorTarget] != nTarget)
+ {
+ if(g_PlayerStates[client][nSpectatorTarget] != -1 && g_PlayerStates[client][nSpectatorTarget] > 0 && g_PlayerStates[client][nSpectatorTarget] < MaxClients)
+ {
+ g_PlayerStates[g_PlayerStates[client][nSpectatorTarget]][nSpectators]--;
+ }
+
+ if( nTarget > 0 && nTarget < MaxClients ) {
+ g_PlayerStates[nTarget][nSpectators]++;
+ }
+ g_PlayerStates[client][nSpectatorTarget] = nTarget;
+ }
+ }
+ }
+ else
+ {
+ if(g_PlayerStates[client][nSpectatorTarget] != -1)
+ {
+ if(g_PlayerStates[client][nSpectatorTarget] > 0 && g_PlayerStates[client][nSpectatorTarget] < MaxClients)
+ {
+ g_PlayerStates[g_PlayerStates[client][nSpectatorTarget]][nSpectators]--;
+ }
+ g_PlayerStates[client][nSpectatorTarget] = -1;
+ }
+ }
+
+ return;
+ }
+ else
+ {
+ if(g_PlayerStates[client][nSpectatorTarget] != -1)
+ {
+ g_PlayerStates[g_PlayerStates[client][nSpectatorTarget]][nSpectators]--;
+ g_PlayerStates[client][nSpectatorTarget] = -1;
+ }
+ }
+
+ if(!g_PlayerStates[client][bOnGround])
+ CheckValidJump(client);
+
+
+ // BEAMU
+ if(g_PlayerStates[client][bBeam] && !bGround && (g_PlayerStates[client][bShowBhopStats] || g_PlayerStates[client][nBhops] < 2))
+ {
+ new Float:v1[3], Float:v2[3];
+ v1[0] = vOrigin[0];
+ v1[1] = vOrigin[1];
+ v1[2] = g_PlayerStates[client][vJumpOrigin][2];
+
+ v2[0] = g_PlayerStates[client][vLastOrigin][0];
+ v2[1] = g_PlayerStates[client][vLastOrigin][1];
+ v2[2] = g_PlayerStates[client][vJumpOrigin][2];
+
+ new color[4] = {255, 255, 255, 100};
+
+ if(g_PlayerStates[client][CurStrafeDir] % STRAFE_DIRECTION:2)
+ {
+ color[0] = 128;
+ color[1] = 128;
+ }
+
+ TE_SetupBeamPoints(v1, v2, g_BeamModel, 0, 0, 0, 10.0, 3.0, 3.0, 10, 0.0, color, 0);
+ TE_SendToClient(client);
+ }
+
+
+ // Call PlayerJump for ladder jumps or walking off the edge
+ if(GetEntityMoveType(client) == MOVETYPE_LADDER)
+ {
+ g_PlayerStates[client][bOnLadder] = true;
+ }
+ else
+ {
+ if(g_PlayerStates[client][bOnLadder])
+ {
+ PlayerJump(client, JT_LADDERJUMP);
+ }
+
+ g_PlayerStates[client][bOnLadder] = false;
+ }
+
+ if(!bGround)
+ {
+ if(g_PlayerStates[client][bOnGround])
+ {
+ PlayerJump(client, JT_DROP);
+ }
+ }
+
+
+ if(g_PlayerStates[client][bOnGround] || g_PlayerStates[client][nStrafes] >= MAX_STRAFES || (!g_PlayerStates[client][bLJEnabled] && !g_PlayerStates[client][nSpectators]) || g_PlayerStates[client][bFailedBlock])
+ {
+ // dumb language
+ if((bGround || g_PlayerStates[client][bOnLadder]) && !g_PlayerStates[client][bOnGround])
+ {
+ PlayerLand(client);
+ }
+
+ #if defined LJSERV
+ if(g_PlayerStates[client][bLJEnabled] && g_PlayerStates[client][bShowPrestrafeHint])
+ {
+ PrintPrestrafeHint(client);
+ }
+ #endif
+
+ return;
+ }
+
+
+ if(!bGround)
+ {
+ g_PlayerStates[client][nLastAerialTick] = GetGameTickCount();
+
+ if(GetVSpeed(vVelocity) > g_PlayerStates[client][fMaxSpeed])
+ g_PlayerStates[client][fMaxSpeed] = GetVSpeed(vVelocity);
+
+ if(vOrigin[2] - g_PlayerStates[client][vJumpOrigin][2] > g_PlayerStates[client][fJumpHeight])
+ g_PlayerStates[client][fJumpHeight] = vOrigin[2] - g_PlayerStates[client][vJumpOrigin][2];
+
+ // Record the failed distance, but since it will trigger if you duck late, only save it if it's certain that the player will not land
+ if(g_PlayerStates[client][bBlockMode] &&
+ !g_PlayerStates[client][bFailedBlock] &&
+ (bDucked && vOrigin[2] <= g_PlayerStates[client][vJumpOrigin][2] + 1.0 ||
+ !bDucked && vOrigin[2] <= g_PlayerStates[client][vJumpOrigin][2] + 1.5) &&
+ vOrigin[2] >= g_PlayerStates[client][vJumpOrigin][2] + HEIGHT_DELTA_MIN(JT_LONGJUMP))
+ {
+ GetJumpDistance(client);
+ #if defined DEBUG
+ PrintToChat(client, "getting failed dist, %d, %f, %f",
+ vOrigin[2] >= g_PlayerStates[client][vJumpOrigin][2] + HEIGHT_DELTA_MIN(JT_LONGJUMP), vOrigin[2], g_PlayerStates[client][vJumpOrigin][2] + HEIGHT_DELTA_MIN(JT_LONGJUMP));
+ #endif
+ }
+
+
+ #if defined DEBUG
+ if(vOrigin[2] <= g_PlayerStates[client][vJumpOrigin][2])
+ {
+ PrintToChat(client, "%d, %d, %d", bDucked, vOrigin[2] <= g_PlayerStates[client][vJumpOrigin][2] + HEIGHT_DELTA_MIN(JT_LONGJUMP), !bDucked && vOrigin[2] <= g_PlayerStates[client][vJumpOrigin][2] - 10.5);
+ }
+ #endif
+
+ // Check if the player is still capable of landing
+ if(g_PlayerStates[client][bBlockMode] && !g_PlayerStates[client][bFailedBlock] &&
+ (bDucked && vOrigin[2] <= g_PlayerStates[client][vJumpOrigin][2] + HEIGHT_DELTA_MIN(JT_LONGJUMP)/* + 1.0*/ || // You land at 0.79 elevation when ducking
+ !bDucked && vOrigin[2] <= g_PlayerStates[client][vJumpOrigin][2] - 10.5))
+ // Ducking increases your origin by 8.5; you land at 1.47 units elevation when ducking, so around 10.0; 10.5 for good measure
+ {
+ StopBeam(client);
+
+ g_PlayerStates[client][bDuck] = bDucked;
+ g_PlayerStates[client][bFailedBlock] = true;
+
+ #if defined DEBUG
+ PrintToChat(client, "failedblocklongjump 1 %.2f, %d", vOrigin[2] - g_PlayerStates[client][vJumpOrigin][2], GetGameTickCount());
+ #endif
+
+ if(bGround && !g_PlayerStates[client][bOnGround])
+ {
+ PlayerLand(client);
+ }
+
+ #if defined LJSERV
+ if(g_PlayerStates[client][bLJEnabled] && g_PlayerStates[client][bShowPrestrafeHint])
+ {
+ PrintPrestrafeHint(client);
+ }
+ #endif
+
+ return;
+ }
+ }
+
+
+ if(g_PlayerStates[client][JumpDir] == JD_BACKWARDS)
+ {
+ new Float:vAnglesUV[3];
+ TBAnglesToUV(vAnglesUV, vAngles);
+
+ new Float:vVelocityDir[3];
+ vVelocityDir = vVelocity;
+ vVelocityDir[2] = 0.0;
+ NormalizeVector(vVelocityDir, vVelocityDir);
+
+ if(ArcCosine(GetVectorDotProduct(vAnglesUV, vVelocityDir)) < FLOAT_PI / 2)
+ {
+ g_PlayerStates[client][JumpDir] = JD_NORMAL;
+ }
+ }
+
+ // check for multiple keys -- it will spam strafes when multiple are held without this
+ new nButtonCount;
+ if(buttons & IN_MOVELEFT)
+ nButtonCount++;
+ if(buttons & IN_MOVERIGHT)
+ nButtonCount++;
+ if(buttons & IN_FORWARD)
+ nButtonCount++;
+ if(buttons & IN_BACK)
+ nButtonCount++;
+
+ if(nButtonCount == 1)
+ {
+ if(g_PlayerStates[client][CurStrafeDir] != SD_A && buttons & IN_MOVELEFT)
+ {
+ if(g_PlayerStates[client][JumpDir] == JD_NONE)
+ {
+ new Float:vAnglesUV[3];
+ TBAnglesToUV(vAnglesUV, vAngles);
+
+ new Float:vVelocityDir[3];
+ vVelocityDir = vVelocity;
+ vVelocityDir[2] = 0.0;
+ NormalizeVector(vVelocityDir, vVelocityDir);
+
+ if(ArcCosine(GetVectorDotProduct(vAnglesUV, vVelocityDir)) > FLOAT_PI / 2)
+ {
+ g_PlayerStates[client][JumpDir] = JD_BACKWARDS;
+ }
+ else
+ {
+ g_PlayerStates[client][JumpDir] = JD_NORMAL;
+ }
+ }
+
+ if(g_PlayerStates[client][JumpDir] == JD_SIDEWAYS)
+ {
+ g_PlayerStates[client][JumpDir] = JD_NORMAL;
+ }
+
+ g_PlayerStates[client][StrafeDir][g_PlayerStates[client][nStrafes]] = SD_A;
+ g_PlayerStates[client][CurStrafeDir] = SD_A;
+ g_PlayerStates[client][nStrafes]++;
+ }
+ else if(g_PlayerStates[client][CurStrafeDir] != SD_D && buttons & IN_MOVERIGHT)
+ {
+ if(g_PlayerStates[client][JumpDir] == JD_NONE)
+ {
+ new Float:vAnglesUV[3];
+ TBAnglesToUV(vAnglesUV, vAngles);
+
+ new Float:vVelocityDir[3];
+ vVelocityDir = vVelocity;
+ vVelocityDir[2] = 0.0;
+ NormalizeVector(vVelocityDir, vVelocityDir);
+
+ if(ArcCosine(GetVectorDotProduct(vAnglesUV, vVelocityDir)) > FLOAT_PI / 2)
+ {
+ g_PlayerStates[client][JumpDir] = JD_BACKWARDS;
+ }
+ else
+ {
+ g_PlayerStates[client][JumpDir] = JD_NORMAL;
+ }
+ }
+
+ else if(g_PlayerStates[client][JumpDir] == JD_SIDEWAYS)
+ {
+ g_PlayerStates[client][JumpDir] = JD_NORMAL;
+ }
+
+ g_PlayerStates[client][StrafeDir][g_PlayerStates[client][nStrafes]] = SD_D;
+ g_PlayerStates[client][CurStrafeDir] = SD_D;
+ g_PlayerStates[client][nStrafes]++;
+ }
+ else if(g_PlayerStates[client][CurStrafeDir] != SD_W && buttons & IN_FORWARD)
+ {
+ if(g_PlayerStates[client][JumpDir] == JD_NONE && (vVelocity[0] || vVelocity[1]))
+ {
+ new Float:vAnglesUV[3];
+ TBAnglesToUV(vAnglesUV, vAngles);
+
+ new Float:vVelocityDir[3];
+ vVelocityDir = vVelocity;
+ vVelocityDir[2] = 0.0;
+ NormalizeVector(vVelocityDir, vVelocityDir);
+
+ if(DegToRad(90.0 - SW_ANGLE_THRESHOLD) < ArcCosine(GetVectorDotProduct(vAnglesUV, vVelocityDir)) < DegToRad(90.0 + SW_ANGLE_THRESHOLD))
+ {
+ g_PlayerStates[client][JumpDir] = JD_SIDEWAYS;
+ }
+ }
+
+ g_PlayerStates[client][StrafeDir][g_PlayerStates[client][nStrafes]] = SD_W;
+ g_PlayerStates[client][CurStrafeDir] = SD_W;
+ g_PlayerStates[client][nStrafes]++;
+ }
+ else if(g_PlayerStates[client][CurStrafeDir] != SD_S && buttons & IN_BACK)
+ {
+ if(g_PlayerStates[client][JumpDir] == JD_NONE && (vVelocity[0] || vVelocity[1]))
+ {
+ new Float:vAnglesUV[3];
+ TBAnglesToUV(vAnglesUV, vAngles);
+
+ new Float:vVelocityDir[3];
+ vVelocityDir = vVelocity;
+ vVelocityDir[2] = 0.0;
+ NormalizeVector(vVelocityDir, vVelocityDir);
+
+ if(DegToRad(90.0 - SW_ANGLE_THRESHOLD) < ArcCosine(GetVectorDotProduct(vAnglesUV, vVelocityDir)) < DegToRad(90.0 + SW_ANGLE_THRESHOLD))
+ {
+ g_PlayerStates[client][JumpDir] = JD_SIDEWAYS;
+ }
+ }
+
+ g_PlayerStates[client][StrafeDir][g_PlayerStates[client][nStrafes]] = SD_S;
+ g_PlayerStates[client][CurStrafeDir] = SD_S;
+ g_PlayerStates[client][nStrafes]++;
+ }
+ }
+
+ if(g_PlayerStates[client][nStrafes] > 0)
+ {
+ new Float:v[3], Float:v2[3];
+ Array_Copy(g_PlayerStates[client][vLastVelocity], v, 3);
+ Array_Copy(g_PlayerStates[client][vLastAngles], v2, 3);
+
+ new Float:fVelDelta = GetSpeed(client) - GetVSpeed(v);
+
+ new Float:fAngleDelta = fmod((FloatAbs(vAngles[1] - v2[1]) + 180.0), 360.0) - 180.0;
+
+ g_PlayerStates[client][nStrafeTicks][g_PlayerStates[client][nStrafes] - 1]++;
+
+ g_PlayerStates[client][fTotalAngle] += fAngleDelta;
+
+ if(fVelDelta > 0.0)
+ {
+ g_PlayerStates[client][fStrafeGain][g_PlayerStates[client][nStrafes] - 1] += fVelDelta;
+ g_PlayerStates[client][fGain] += fVelDelta;
+
+ g_PlayerStates[client][nStrafeTicksSynced][g_PlayerStates[client][nStrafes] - 1]++;
+
+ g_PlayerStates[client][fSyncedAngle] += fAngleDelta;
+ }
+ else
+ {
+ g_PlayerStates[client][fStrafeLoss][g_PlayerStates[client][nStrafes] - 1] -= fVelDelta;
+ g_PlayerStates[client][fLoss] -= fVelDelta;
+ }
+ }
+
+ g_PlayerStates[client][nTotalTicks]++;
+ g_PlayerStates[client][fTrajectory] += GetSpeed(client) * GetTickInterval();
+
+ if(bGround && !g_PlayerStates[client][bOnGround])
+ {
+ PlayerLand(client);
+ }
+
+ #if defined LJSERV
+ if(g_PlayerStates[client][bLJEnabled] && g_PlayerStates[client][bShowPrestrafeHint])
+ {
+ PrintPrestrafeHint(client);
+ }
+ #endif
+}
+
+public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:vAngles[3], &weapon)
+{
+ new Float:vOrigin[3], Float:vVelocity[3];
+ new bool:bDucked = bool:GetEntProp(client, Prop_Send, "m_bDucked", 1), bool:bGround = bool:(GetEntityFlags(client) & FL_ONGROUND);
+ GetClientAbsOrigin(client, vOrigin);
+ GetEntPropVector(client, Prop_Data, "m_vecVelocity", vVelocity);
+
+ _OnPlayerRunCmd(client, buttons, vOrigin, vAngles, vVelocity, bDucked, bGround);
+
+ Array_Copy(vOrigin, g_PlayerStates[client][vLastOrigin], 3);
+ Array_Copy(vAngles, g_PlayerStates[client][vLastAngles], 3);
+ Array_Copy(vVelocity, g_PlayerStates[client][vLastVelocity], 3);
+ g_PlayerStates[client][bSecondLastDuckState] = g_PlayerStates[client][bLastDuckState];
+ g_PlayerStates[client][bLastDuckState] = bDucked;
+ g_PlayerStates[client][LastButtons] = buttons;
+
+ return Plugin_Continue;
+}
+
+#if defined LJSERV
+PrintPrestrafeHint(client)
+{
+ new bool:bGround = bool:(GetEntityFlags(client) & FL_ONGROUND);
+ decl String:strHint[128];
+
+ Format(strHint, sizeof(strHint), "Pre: %.2f", bGround && !GetEntPropFloat(client, Prop_Send, "m_flStamina") ? GetSpeed(client) : g_PlayerStates[client][fPrestrafe]);
+
+ if(g_PlayerStates[client][fEdge] != -1.0 && !bGround)
+ {
+ Append(strHint, sizeof(strHint), " | e: %.2f", g_PlayerStates[client][fEdge]);
+ }
+
+ if(!bGround)
+ {
+ Append(strHint, sizeof(strHint), "\nG: %d | L: %d\nMaxspeed: %d", RoundFloat(g_PlayerStates[client][fGain]), RoundFloat(g_PlayerStates[client][fLoss]), RoundFloat(g_PlayerStates[client][fMaxSpeed]));
+ }
+
+ PrintHintText(client, strHint);
+}
+#endif
+
+PlayerLand(client)
+{
+ g_PlayerStates[client][bOnGround] = true;
+
+ g_PlayerStates[client][fLandTime] = GetGameTime();
+
+ if(!g_PlayerStates[client][bLJEnabled] && !g_PlayerStates[client][nSpectators] || !g_PlayerStates[client][bShowBhopStats] && g_PlayerStates[client][nBhops] > 1)
+ return;
+
+
+
+ // Final CheckValidJump
+ //CheckValidJump(client);
+
+
+ new Float:vCurOrigin[3];
+ GetClientAbsOrigin(client, vCurOrigin);
+ g_PlayerStates[client][fFinalSpeed] = GetSpeed(client);
+
+
+ #if defined DEBUG
+ if(g_PlayerStates[client][bFailedBlock] && vCurOrigin[2] - g_PlayerStates[client][vJumpOrigin][2] > -2.0)
+ PrintToChat(client, "failed block && height delta = %f", vCurOrigin[2] - g_PlayerStates[client][vJumpOrigin][2]);
+
+ PrintToChat(client, "%d", g_PlayerStates[client][bFailedBlock]);
+ #endif
+
+ // Calculate distances
+ if(!g_PlayerStates[client][bFailedBlock])// || // if block longjump failed, distances have already been written in mid-air.
+ //vCurOrigin[2] - g_PlayerStates[client][vJumpOrigin][2] >= HEIGHT_DELTA_MIN(JT_LONGJUMP)) // bugs sometimes if you land on last tick (I think) idk how else 2 fix
+ {
+ GetJumpDistance(client);
+
+ g_PlayerStates[client][bFailedBlock] = false;
+ }
+
+ // don't show drop stats
+ if(g_PlayerStates[client][JumpType] == JT_DROP)
+ return;
+
+ if(!g_PlayerStates[client][bShowAllJumps])
+ {
+ if(g_PlayerStates[client][JumpType] == JT_LONGJUMP)
+ {
+ if(g_PlayerStates[client][fHeightDelta] > HEIGHT_DELTA_MIN(g_PlayerStates[client][JumpType]) && g_PlayerStates[client][fHeightDelta] < HEIGHT_DELTA_MAX(g_PlayerStates[client][JumpType]))
+ {
+ if(g_PlayerStates[client][fJumpDistance] < 240.0)
+ {
+ return;
+ }
+ }
+ else // Dropjump/upjump
+ {
+ if(g_PlayerStates[client][fJumpDistance] < 240.0 - g_PlayerStates[client][fHeightDelta])
+ {
+ return;
+ }
+ }
+ }
+ else if(g_PlayerStates[client][fJumpDistance] < 240.0)
+ {
+ return;
+ }
+ }
+
+ // Check whether the player actually moved past the block edge
+ if(g_PlayerStates[client][bBlockMode] && !g_PlayerStates[client][bFailedBlock])
+ {
+ if(!g_PlayerStates[client][vBlockNormal][0] || !g_PlayerStates[client][vBlockNormal][1])
+ {
+ // bools are not actually handled as 1 bit bools but 32 bit cells so n = normal.y gives out of bounds exception
+ // !!normal.y or !normal.x rather
+ // pawn good
+ new bool:n = !g_PlayerStates[client][vBlockNormal][0];
+
+ if(g_PlayerStates[client][vBlockNormal][n] > 0.0)
+ {
+ if(vCurOrigin[n] + 16.0 * g_PlayerStates[client][vBlockNormal][n] < g_PlayerStates[client][vBlockEndPos][n])
+ {
+ g_PlayerStates[client][bFailedBlock] = true;
+ }
+ }
+ else
+ {
+ if(vCurOrigin[n] + 16.0 * g_PlayerStates[client][vBlockNormal][n] > g_PlayerStates[client][vBlockEndPos][n])
+ {
+ g_PlayerStates[client][bFailedBlock] = true;
+ }
+ }
+ }
+ else
+ {
+ new Float:vAdjCurOrigin[3], Float:vInvNormal[3];
+ vAdjCurOrigin = vCurOrigin;
+ Array_Copy(g_PlayerStates[client][vBlockNormal], vInvNormal, 2);
+ ScaleVector(vInvNormal, -1.0);
+ Adjust(vAdjCurOrigin, vInvNormal);
+
+
+ // f(endpos.x) + (origin.x - endpos.x) * b = (f(endpos.x) - endpos.x * b) + origin.x * b = f(0) + origin.x * b
+ // block normal is perpendicular to the edge direction, so b = 1 / (normal rot 90).x
+ // dx and dy should have same sign so ccw rot if facing down, cw rot if up
+ new Float:b = 1 / (g_PlayerStates[client][vBlockNormal][0] < 0 ? g_PlayerStates[client][vBlockNormal][1] : -g_PlayerStates[client][vBlockNormal][1]);
+ new Float:fPos = g_PlayerStates[client][vBlockEndPos][1] + (vAdjCurOrigin[0] - g_PlayerStates[client][vBlockEndPos][0]) * b;
+
+ if(g_PlayerStates[client][vBlockNormal][1] > 0.0 ? vAdjCurOrigin[1] < fPos : vAdjCurOrigin[1] > fPos)
+ {
+ g_PlayerStates[client][bFailedBlock] = true;
+ }
+
+
+ #if defined DEBUG
+ PrintToChat(client, "block normal: %.2f, %.2f\n%.2f, %.2f, %.2f",
+ g_PlayerStates[client][vBlockNormal][0],
+ g_PlayerStates[client][vBlockNormal][1],
+ vAdjCurOrigin[1],
+ fPos,
+ g_PlayerStates[client][vBlockEndPos][1]);
+
+ new Float:v1[3], Float:v2[3];
+ v1[2] = g_PlayerStates[client][vBlockEndPos][2] + 0.1;
+ v2[2] = g_PlayerStates[client][vBlockEndPos][2] + 0.1;
+ v1[0] = g_PlayerStates[client][vBlockEndPos][0] - 50;
+ v1[1] = g_PlayerStates[client][vBlockEndPos][1] + (v1[0] - g_PlayerStates[client][vBlockEndPos][0]) * b;
+ v2[0] = g_PlayerStates[client][vBlockEndPos][0] + 50;
+ v2[1] = g_PlayerStates[client][vBlockEndPos][1] + (v2[0] - g_PlayerStates[client][vBlockEndPos][0]) * b;
+ CreateBeam2(v1, v2, 0, 0, 255);
+
+ if(g_PlayerStates[client][bFailedBlock])
+ {
+ PrintToChat(client, "failedblocklongjump 2");
+ }
+ #endif
+ }
+ }
+
+
+ // sum sync
+ g_PlayerStates[client][fSync] = 0.0;
+
+ for(new i = 0; i < g_PlayerStates[client][nStrafes] && i < MAX_STRAFES; i++)
+ {
+ g_PlayerStates[client][fSync] += g_PlayerStates[client][nStrafeTicksSynced][i];
+ g_PlayerStates[client][fStrafeSync][i] = float(g_PlayerStates[client][nStrafeTicksSynced][i]) / g_PlayerStates[client][nStrafeTicks][i] * 100;
+ }
+
+ g_PlayerStates[client][fSync] /= g_PlayerStates[client][nTotalTicks];
+ g_PlayerStates[client][fSync] *= 100;
+
+
+
+
+ ////
+ // Write HUD hint
+ ////
+
+ decl String:buf[1024];
+
+ g_PlayerStates[client][strHUDHint][0] = 0;
+
+ if(g_PlayerStates[client][bBlockMode])
+ {
+ if(g_PlayerStates[client][fBlockDistance] != -1.0)
+ {
+ Format(buf, sizeof(buf), "%.1f block %s\n",
+ g_PlayerStates[client][fBlockDistance],
+ g_PlayerStates[client][bFailedBlock] ? "(failed)" : "");
+
+ StrCat(g_PlayerStates[client][strHUDHint], HUD_HINT_SIZE, buf);
+ }
+ else
+ {
+ Format(buf, sizeof(buf), "??? block %s\n",
+ g_PlayerStates[client][bFailedBlock] ? "(failed) " : "");
+
+ StrCat(g_PlayerStates[client][strHUDHint], HUD_HINT_SIZE, buf);
+ }
+
+ if(g_PlayerStates[client][fBlockDistance] != -1.0 && g_PlayerStates[client][vBlockNormal][0] != 0.0 && g_PlayerStates[client][vBlockNormal][1] != 0.0 && g_PlayerStates[client][nVerbosity] > 2)
+ {
+ new Float:f = 32.0 * (FloatAbs(g_PlayerStates[client][vBlockNormal][0]) + FloatAbs(g_PlayerStates[client][vBlockNormal][1]) - 1.0);
+ new Float:fAngle = FloatAbs(RadToDeg(ArcSine(g_PlayerStates[client][vBlockNormal][0])));
+ fAngle = fAngle <= 45.0 ? fAngle : 90 - fAngle;
+
+ Format(buf, sizeof(buf), "(%.1f rotated by %.1fÂș)\n",
+ g_PlayerStates[client][fBlockDistance] + f,
+ fAngle);
+
+ StrCat(g_PlayerStates[client][strHUDHint], HUD_HINT_SIZE, buf);
+ }
+
+ if(g_PlayerStates[client][fBlockDistance] != -1.0 && g_PlayerStates[client][nVerbosity] > 1)
+ {
+ new Float:vJumpAngle[3], Float:vJumpOrig[3], Float:vBlockN[3];
+
+ vJumpAngle = vCurOrigin;
+ Array_Copy(g_PlayerStates[client][vJumpOrigin], vJumpOrig, 3);
+
+ vBlockN[0] = g_PlayerStates[client][vBlockNormal][0];
+ vBlockN[1] = g_PlayerStates[client][vBlockNormal][1];
+
+ vJumpAngle[2] = 0.0;
+ vJumpOrig[2] = 0.0;
+
+ SubtractVectors(vJumpAngle, vJumpOrig, vJumpAngle);
+ NormalizeVector(vJumpAngle, vJumpAngle);
+
+ Format(buf, sizeof(buf), "%.2f degrees off block\n",
+ RadToDeg(ArcCosine(GetVectorDotProduct(vJumpAngle, vBlockN))));
+
+ StrCat(g_PlayerStates[client][strHUDHint], HUD_HINT_SIZE, buf);
+ }
+ }
+
+ decl String:strJump[32];
+
+ if(g_PlayerStates[client][fHeightDelta] > HEIGHT_DELTA_MAX(g_PlayerStates[client][JumpType]))
+ {
+ if(g_PlayerStates[client][JumpType] == JT_LONGJUMP)
+ {
+ strJump = "Upjump";
+ }
+ else
+ {
+ Format(strJump, sizeof(strJump), "Up%s", g_strJumpTypeLwr[g_PlayerStates[client][JumpType]]);
+ }
+ }
+ else if(g_PlayerStates[client][fHeightDelta] < HEIGHT_DELTA_MIN(g_PlayerStates[client][JumpType]))
+ {
+ if(g_PlayerStates[client][JumpType] == JT_LONGJUMP)
+ {
+ strJump = "Dropjump";
+ }
+ else
+ {
+ Format(strJump, sizeof(strJump), "Drop%s", g_strJumpTypeLwr[g_PlayerStates[client][JumpType]]);
+ }
+ }
+ else
+ {
+ strcopy(strJump, sizeof(strJump), g_strJumpType[g_PlayerStates[client][JumpType]]);
+ }
+
+ decl String:strJumpDir[16];
+ strJumpDir = g_PlayerStates[client][JumpDir] == JD_SIDEWAYS ? " sideways" : g_PlayerStates[client][JumpDir] == JD_BACKWARDS ? " backwards" : "";
+
+ Format(buf, sizeof(buf), "%s%s%s\npre: %.2f",
+ strJump, strJumpDir,
+ g_PlayerStates[client][JumpType] == JT_LONGJUMP &&
+ g_PlayerStates[client][fHeightDelta] >= HEIGHT_DELTA_MIN(g_PlayerStates[client][JumpType]) &&
+ g_PlayerStates[client][IllegalJumpFlags] == IJF_NONE &&
+ g_PlayerStates[client][nTotalTicks] > 77 ? " (extended)" : "",
+ g_PlayerStates[client][fPrestrafe]);
+
+ StrCat(g_PlayerStates[client][strHUDHint], HUD_HINT_SIZE, buf);
+
+ if(g_PlayerStates[client][JumpType] == JT_WEIRDJUMP && g_PlayerStates[client][nVerbosity] > 1)
+ {
+ Format(buf, sizeof(buf), " (%.2f)",
+ g_PlayerStates[client][fWJDropPre]);
+
+ StrCat(g_PlayerStates[client][strHUDHint], HUD_HINT_SIZE, buf);
+ }
+
+ Format(buf, sizeof(buf), "; dist: %.2f",
+ g_PlayerStates[client][fJumpDistance]);
+
+ StrCat(g_PlayerStates[client][strHUDHint], HUD_HINT_SIZE, buf);
+
+ if(g_PlayerStates[client][fEdge] != -1.0)
+ {
+ Format(buf, sizeof(buf), "; edge: %.2f",
+ g_PlayerStates[client][fEdge]);
+
+ StrCat(g_PlayerStates[client][strHUDHint], HUD_HINT_SIZE, buf);
+ }
+
+ StrCat(g_PlayerStates[client][strHUDHint], HUD_HINT_SIZE, "\n");
+
+ Format(buf, sizeof(buf), "%d; %.2f%; %.2f (%.2f)",
+ g_PlayerStates[client][nStrafes],
+ g_PlayerStates[client][fSync],
+ g_PlayerStates[client][fMaxSpeed],
+ g_PlayerStates[client][fMaxSpeed] - g_PlayerStates[client][fPrestrafe]);
+
+ StrCat(g_PlayerStates[client][strHUDHint], HUD_HINT_SIZE, buf);
+
+ if(g_PlayerStates[client][nVerbosity] > 2)
+ {
+ Format(buf, sizeof(buf), "\n%s%.2f; %.2f; %.4f%; %d",
+ g_PlayerStates[client][fHeightDelta] >= 0.0 ? "+" : "",
+ g_PlayerStates[client][fHeightDelta],
+ g_PlayerStates[client][fJumpHeight],
+ (g_PlayerStates[client][fJumpDistance] - 32.0) / g_PlayerStates[client][fTrajectory],
+ g_PlayerStates[client][nTotalTicks]);
+
+ StrCat(g_PlayerStates[client][strHUDHint], HUD_HINT_SIZE, buf);
+ }
+
+
+ if(g_PlayerStates[client][bLJEnabled])
+ {
+ buf[0] = 0;
+
+ Append(buf, sizeof(buf), "\n");
+
+ if(g_PlayerStates[client][bBlockMode])
+ {
+ if(g_PlayerStates[client][fBlockDistance] != -1.0)
+ {
+ Append(buf, sizeof(buf), "%.01f block%s",
+ g_PlayerStates[client][fBlockDistance],
+ g_PlayerStates[client][bFailedBlock] ? " (failed)" : "");
+ }
+ else
+ {
+ Append(buf, sizeof(buf), "??? block%s",
+ g_PlayerStates[client][bFailedBlock] ? " (failed)" : "");
+ }
+
+ if(g_PlayerStates[client][fBlockDistance] != -1.0 && g_PlayerStates[client][vBlockNormal][0] != 0.0 && g_PlayerStates[client][vBlockNormal][1] != 0.0)
+ {
+ new Float:f = 32.0 * (FloatAbs(g_PlayerStates[client][vBlockNormal][0]) + FloatAbs(g_PlayerStates[client][vBlockNormal][1]) - 1.0);
+ new Float:fAngle = FloatAbs(RadToDeg(ArcSine(g_PlayerStates[client][vBlockNormal][0])));
+ fAngle = fAngle <= 45.0 ? fAngle : 90 - fAngle;
+
+ Append(buf, sizeof(buf), " (%.1f rotated by %.1f)",
+ g_PlayerStates[client][fBlockDistance] + f,
+ fAngle);
+ }
+
+ if(g_PlayerStates[client][fBlockDistance] != -1.0)
+ {
+ new Float:vJumpAngle[3], Float:vJumpOrig[3], Float:vBlockN[3];
+
+ vJumpAngle = vCurOrigin;
+ Array_Copy(g_PlayerStates[client][vJumpOrigin], vJumpOrig, 3);
+
+ vBlockN[0] = g_PlayerStates[client][vBlockNormal][0];
+ vBlockN[1] = g_PlayerStates[client][vBlockNormal][1];
+
+ vJumpAngle[2] = 0.0;
+ vJumpOrig[2] = 0.0;
+
+ SubtractVectors(vJumpAngle, vJumpOrig, vJumpAngle);
+ NormalizeVector(vJumpAngle, vJumpAngle);
+
+ Append(buf, sizeof(buf), " - %.2f degrees off block",
+ RadToDeg(ArcCosine(GetVectorDotProduct(vJumpAngle, vBlockN))));
+ }
+
+ Append(buf, sizeof(buf), "\n");
+ }
+
+ Append(buf, sizeof(buf), "%s%s%s\nDistance: %.2f",
+ strJump, strJumpDir,
+ g_PlayerStates[client][JumpType] == JT_LONGJUMP &&
+ g_PlayerStates[client][fHeightDelta] > HEIGHT_DELTA_MIN(g_PlayerStates[client][JumpType])
+ && g_PlayerStates[client][nTotalTicks] > 77 ? " (extended)" : "",
+ g_PlayerStates[client][fJumpDistance]);
+
+ Append(buf, sizeof(buf), "; prestrafe: %.2f",
+ g_PlayerStates[client][fPrestrafe]);
+
+ if(g_PlayerStates[client][JumpType] == JT_WEIRDJUMP)
+ {
+ Append(buf, sizeof(buf), "; drop prestrafe: %.2f",
+ g_PlayerStates[client][fWJDropPre]);
+ }
+
+ if(g_PlayerStates[client][fEdge] != -1.0)
+ {
+ Append(buf, sizeof(buf), "; edge: %.2f",
+ g_PlayerStates[client][fEdge]);
+ }
+
+ if(g_PlayerStates[client][nTotalTicks] == 78)
+ {
+ new Float:vCurOrigin2[3];
+ Array_Copy(g_PlayerStates[client][vLastOrigin], vCurOrigin2, 3);
+
+ vCurOrigin2[2] = 0.0;
+
+ new Float:v[3];
+ Array_Copy(g_PlayerStates[client][vJumpOrigin], v, 3);
+
+ v[2] = 0.0;
+
+ new Float:ProjDist = GetVectorDistance(v, vCurOrigin2) + 32.0;
+
+ Append(buf, sizeof(buf), "; projected real distance: %.2f", ProjDist);
+ }
+
+ Append(buf, sizeof(buf), "\nStrafes: %d; sync: %.2f%%; maxspeed (gain): %.2f (%.2f)",
+ g_PlayerStates[client][nStrafes],
+ g_PlayerStates[client][fSync],
+ g_PlayerStates[client][fMaxSpeed],
+ g_PlayerStates[client][fMaxSpeed] - g_PlayerStates[client][fPrestrafe]);
+
+ Append(buf, sizeof(buf), "\nHeight diff: %s%.2f; jump height: %.2f; efficiency: %.4f; ticks: %d; degrees synced/degrees turned: %.2f/%.2f",
+ g_PlayerStates[client][fHeightDelta] >= 0.0 ? "+" : "",
+ g_PlayerStates[client][fHeightDelta],
+ g_PlayerStates[client][fJumpHeight],
+ (g_PlayerStates[client][fJumpDistance] - 32.0) / g_PlayerStates[client][fTrajectory],
+ g_PlayerStates[client][nTotalTicks],
+ g_PlayerStates[client][fSyncedAngle], g_PlayerStates[client][fTotalAngle]);
+
+ PrintToConsole(client, buf);
+
+
+ new Handle:hBuffer = StartMessageOne("KeyHintText", client);
+ BfWriteByte(hBuffer, 1);
+ BfWriteString(hBuffer, g_PlayerStates[client][strHUDHint]);
+ EndMessage();
+ }
+
+
+ ////
+ // Panel
+ ////
+
+ new Handle:hStatsPanel = CreatePanel();
+
+
+ Format(buf, 128, "%s %.2f %s%.2f",
+ g_strJumpTypeShort[g_PlayerStates[client][JumpType]],
+ g_PlayerStates[client][fJumpDistance],
+ g_PlayerStates[client][fHeightDelta] > 0.01 ? "+" : "",
+ g_PlayerStates[client][fHeightDelta]);
+
+ SetPanelTitle(hStatsPanel, buf);
+
+
+ if(g_PlayerStates[client][bLJEnabled])
+ {
+ PrintToConsole(client, "--------------------------------");
+ }
+
+ // Print first 16 strafes to panel
+ for(new i = 0; i < g_PlayerStates[client][nStrafes] && i < 16; i++)
+ {
+ decl String:strStrafeKey[3];
+ GetStrafeKey(strStrafeKey, g_PlayerStates[client][StrafeDir][i]);
+ DrawPanelTextF(hStatsPanel, "%d %s %.2f %.2f %.2f %.2f",
+ i + 1,
+ strStrafeKey,
+ g_PlayerStates[client][fStrafeGain][i], g_PlayerStates[client][fStrafeLoss][i],
+ float(g_PlayerStates[client][nStrafeTicks][i]) / g_PlayerStates[client][nTotalTicks] * 100,
+ float(g_PlayerStates[client][nStrafeTicksSynced][i]) / g_PlayerStates[client][nStrafeTicks][i] * 100);
+ }
+
+ // Print strafes to console
+ if(g_PlayerStates[client][bLJEnabled])
+ {
+ PrintToConsole(client, "# Key Gain Loss Time Sync");
+
+ for(new i = 0; i < g_PlayerStates[client][nStrafes] && i < MAX_STRAFES; i++)
+ {
+ decl String:strStrafeKey[3];
+ GetStrafeKey(strStrafeKey, g_PlayerStates[client][StrafeDir][i]);
+ Format(buf, sizeof(buf), "%d %s %6.2f %6.2f %6.2f %6.2f", i + 1,
+ strStrafeKey,
+ g_PlayerStates[client][fStrafeGain][i], g_PlayerStates[client][fStrafeLoss][i],
+ float(g_PlayerStates[client][nStrafeTicks][i]) / g_PlayerStates[client][nTotalTicks] * 100,
+ float(g_PlayerStates[client][nStrafeTicksSynced][i]) / g_PlayerStates[client][nStrafeTicks][i] * 100);
+
+ PrintToConsole(client, buf);
+ }
+ }
+
+ DrawPanelTextF(hStatsPanel, " %.2f%%", g_PlayerStates[client][fSync]);
+
+ if(g_PlayerStates[client][nVerbosity] > 2)
+ {
+ DrawPanelTextF(hStatsPanel, " %.2f/%.2f", g_PlayerStates[client][fSyncedAngle], g_PlayerStates[client][fTotalAngle]);
+ }
+
+ DrawPanelTextF(hStatsPanel, " %s", g_PlayerStates[client][bDuck] ? "Duck" : g_PlayerStates[client][bLastDuckState] ? "Partial Duck" : "No Duck");
+
+ if(g_PlayerStates[client][bLJEnabled])
+ {
+ /*PrintToConsole(client, " %.2f%%", g_PlayerStates[client][fSync]);
+
+ if(g_nVerbosity > 1)
+ {
+ PrintToConsole(client, " %.2f/%.2f", g_PlayerStates[client][fSyncedAngle], g_PlayerStates[client][fTotalAngle]);
+ }*/
+
+ PrintToConsole(client, " %s", g_PlayerStates[client][bDuck] ? "Duck" : g_PlayerStates[client][bLastDuckState] ? "Partial Duck" : "No Duck");
+
+ PrintToConsole(client, ""); // Newline
+ }
+
+ if(g_PlayerStates[client][bLJEnabled] && g_PlayerStates[client][JumpType] != JT_BHOP && g_PlayerStates[client][IllegalJumpFlags])
+ {
+ PrintToConsole(client, "Illegal jump: ");
+
+ if(g_PlayerStates[client][IllegalJumpFlags] & IJF_WORLD)
+ {
+ PrintToConsole(client, "Lateral world collision (hit wall/surf)");
+ }
+
+ if(g_PlayerStates[client][IllegalJumpFlags] & IJF_BOOSTER)
+ {
+ PrintToConsole(client, "Booster");
+ }
+
+ if(g_PlayerStates[client][IllegalJumpFlags] & IJF_GRAVITY)
+ {
+ PrintToConsole(client, "Gravity");
+ }
+
+ if(g_PlayerStates[client][IllegalJumpFlags] & IJF_TELEPORT)
+ {
+ PrintToConsole(client, "Teleport");
+ }
+
+ if(g_PlayerStates[client][IllegalJumpFlags] & IJF_LAGGEDMOVEMENTVALUE)
+ {
+ PrintToConsole(client, "Lagged movement value");
+ }
+
+ if(g_PlayerStates[client][IllegalJumpFlags] & IJF_PRESTRAFE)
+ {
+ PrintToConsole(client, "Prestrafe > %.2f", g_fLJMaxPrestrafe);
+ }
+
+ if(g_PlayerStates[client][IllegalJumpFlags] & IJF_SCOUT)
+ {
+ PrintToConsole(client, "Scout");
+ }
+
+ if(g_PlayerStates[client][IllegalJumpFlags] & IJF_NOCLIP)
+ {
+ PrintToConsole(client, "noclip");
+ }
+
+ PrintToConsole(client, ""); // Newline
+ }
+
+ if(g_PlayerStates[client][bLJEnabled] && !g_PlayerStates[client][bHidePanel] && g_PlayerStates[client][nVerbosity] > 0 && !(g_PlayerStates[client][bHideBhopPanel] && g_PlayerStates[client][nBhops] > 1))
+ {
+ SendPanelToClient(hStatsPanel, client, EmptyPanelHandler, 5);
+ }
+
+
+
+ // Send to spectators of this player
+ for(new i = 1; i <= MaxClients; i++)
+ {
+ if(IsClientInGame(i) && !IsClientSourceTV(i) && !IsClientReplay(i) && !IsFakeClient(i))
+ {
+ if(g_PlayerStates[i][nSpectatorTarget] == client)
+ {
+ if(g_PlayerStates[i][nVerbosity] > 0 && !g_PlayerStates[i][bHidePanel])
+ {
+ SendPanelToClient(hStatsPanel, i, EmptyPanelHandler, 5);
+ }
+
+ new Handle:hBuffer2 = StartMessageOne("KeyHintText", i);
+ BfWriteByte(hBuffer2, 1);
+ BfWriteString(hBuffer2, g_PlayerStates[client][strHUDHint]);
+ EndMessage();
+ }
+ }
+ }
+
+ CloseHandle(hStatsPanel);
+
+
+ ////
+ // Print chat message
+ ////
+
+ if(!g_PlayerStates[client][bLJEnabled] ||
+ g_PlayerStates[client][IllegalJumpFlags] != IJF_NONE ||
+ g_PlayerStates[client][fHeightDelta] < HEIGHT_DELTA_MIN(JUMP_TYPE:(g_PlayerStates[client][JumpType] == JT_BHOP ? JT_BHOPJUMP : g_PlayerStates[client][JumpType])) ||
+ g_PlayerStates[client][bFailedBlock] && !g_bPrintFailedBlockStats)
+ {
+ return;
+ }
+
+ if(g_PlayerStates[client][JumpType] == JT_BHOPJUMP && g_PlayerStates[client][fLastJumpHeightDelta] < HEIGHT_DELTA_MIN(JT_BHOPJUMP))
+ {
+ return;
+ }
+
+
+ switch(g_PlayerStates[client][JumpType])
+ {
+ case JT_LONGJUMP, JT_COUNTJUMP:
+ {
+ new Float:fMin = (g_fLJNoDuckMin != 0.0 && !g_PlayerStates[client][bDuck] && !g_PlayerStates[client][bLastDuckState]) ? g_fLJNoDuckMin : g_fLJMin;
+
+ if(fMin != 0.0 && g_PlayerStates[client][fJumpDistance] >= fMin)
+ {
+ OutputJump(client, buf);
+ }
+
+ if(g_bLJSound && g_PlayerStates[client][bSound])
+ {
+ for(new i = 0; i < LJSOUND_NUM; i++)
+ {
+ if(g_PlayerStates[client][fJumpDistance] >= g_fLJSound[i])
+ {
+ if(i == LJSOUND_NUM || g_PlayerStates[client][fJumpDistance] < g_fLJSound[i + 1] || g_fLJSound[i + 1] == 0.0)
+ {
+ if(g_bLJSoundToAll[i])
+ {
+ for(new j = 1; j < MaxClients; j++)
+ {
+ if(IsClientInGame(client) && !IsFakeClient(client) && g_PlayerStates[j][bSound] && IsClientInGame(j))
+ {
+ EmitSoundToClient(j, g_strLJSoundFile[i]);
+ }
+ }
+ }
+ else
+ {
+ EmitSoundToClient(client, g_strLJSoundFile[i]);
+ }
+
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ case JT_WEIRDJUMP:
+ {
+ if(g_fWJMin != 0.0 && g_PlayerStates[client][fJumpDistance] > g_fWJMin && (g_fWJDropMax == 0.0 || g_fWJDropMax >= FloatAbs(g_PlayerStates[client][fLastJumpHeightDelta])))
+ {
+ OutputJump(client, buf);
+ }
+ }
+
+ case JT_BHOPJUMP:
+ {
+ if(g_fBJMin != 0.0 && g_PlayerStates[client][fJumpDistance] >= g_fBJMin)
+ {
+ OutputJump(client, buf);
+ }
+ }
+
+ case JT_LADDERJUMP:
+ {
+ if(g_fLAJMin != 0.0 && g_PlayerStates[client][fJumpDistance] >= g_fLAJMin)
+ {
+ OutputJump(client, buf);
+ }
+ }
+ }
+
+ UpdatePersonalBest(client);
+
+ LJTopUpdate(client);
+}
+
+public EmptyPanelHandler(Handle:hPanel, MenuAction:ma, Param1, Param2)
+{
+}
+
+OutputJump(client, String:buf[1024])
+{
+ new Float:fMin = (g_fLJNoDuckMin != 0.0 && !g_PlayerStates[client][bDuck] && !g_PlayerStates[client][bLastDuckState]) ? g_fLJNoDuckMin : g_fLJMin;
+ new Float:fMinClamp = g_fLJMin ? g_fLJMin : g_fLJNoDuckMin ? g_fLJNoDuckMin : g_fLJClientMin;
+ new Float:fMax = g_fLJMax;
+
+ new bool:bPrintToAll = true;
+
+ if(g_PlayerStates[client][JumpType] == JT_LONGJUMP && g_fLJClientMin != 0 && g_PlayerStates[client][fJumpDistance] < fMin)
+ {
+ fMin = g_fLJClientMin;
+ bPrintToAll = false;
+ }
+
+ if(!g_bOutput16Style)
+ {
+ decl String:strOutput[512];
+
+ decl String:strName[64];
+ GetClientName(client, strName, sizeof(strName));
+
+ Format(strOutput, sizeof(strOutput), "%s {green}%s%sed ",
+ strName,
+ g_PlayerStates[client][JumpType] == JT_BHOPJUMP && g_PlayerStates[client][bStamina] ? "easy" : "",
+ g_strJumpTypeLwr[g_PlayerStates[client][JumpType]]);
+
+ if(g_PlayerStates[client][JumpType] != JT_LADDERJUMP)
+ {
+
+ if(g_PlayerStates[client][JumpType] != JT_LONGJUMP && g_PlayerStates[client][JumpType] != JT_COUNTJUMP)
+ {
+ fMax = g_fNonLJMax;
+ }
+
+ new nColor[3];
+ for(new i; i < 3; i++) {
+ nColor[i] = RoundFloat((MIN(MAX(g_PlayerStates[client][fJumpDistance], fMinClamp), fMax) - fMinClamp) /
+ (fMax - fMinClamp) * (g_ColorMax[i] - g_ColorMin[i]) + g_ColorMin[i]);
+ }
+
+ Format(buf, sizeof(buf), "\x07%02X%02X%02X",
+ nColor[0], nColor[1], nColor[2]);
+
+ StrCat(strOutput, sizeof(strOutput), buf);
+ }
+
+ Format(buf, sizeof(buf), "%.2f{green} units", g_PlayerStates[client][fJumpDistance]);
+
+ StrCat(strOutput, sizeof(strOutput), buf);
+
+ if(g_PlayerStates[client][JumpDir] != JD_FORWARDS)
+ {
+ if(g_PlayerStates[client][JumpDir] == JD_SIDEWAYS)
+ {
+ StrCat(strOutput, sizeof(strOutput), " sideways");
+ }
+ else if(g_PlayerStates[client][JumpDir] == JD_BACKWARDS)
+ {
+ StrCat(strOutput, sizeof(strOutput), " backwards");
+ }
+ }
+
+ if(!g_PlayerStates[client][bDuck] && !g_PlayerStates[client][bLastDuckState])
+ {
+ StrCat(strOutput, sizeof(strOutput), " no duck");
+ }
+
+ if(g_PlayerStates[client][bBlockMode])
+ {
+ if(g_PlayerStates[client][fBlockDistance] != -1.0)
+ {
+ Format(buf, sizeof(buf), " @ %.1f block%s", g_PlayerStates[client][fBlockDistance], g_PlayerStates[client][bFailedBlock] ? " (failed)" : "");
+
+ StrCat(strOutput, sizeof(strOutput), buf);
+ }
+ else if(g_PlayerStates[client][bFailedBlock])
+ {
+ StrCat(strOutput, sizeof(strOutput), " @ ? block (failed)");
+ }
+ }
+
+ StrCat(strOutput, sizeof(strOutput), "!");
+
+ if(g_nVerbosity > 1)
+ {
+ Format(buf, sizeof(buf), " ({lightblue}%.2f{green}, {lightblue}%d{green} @ {lightblue}%d%%{green}, {lightblue}%d{green}",
+ g_PlayerStates[client][fPrestrafe], g_PlayerStates[client][nStrafes], RoundFloat(g_PlayerStates[client][fSync]), RoundFloat(g_PlayerStates[client][fMaxSpeed]));
+
+ StrCat(strOutput, sizeof(strOutput), buf);
+ }
+ else if(g_nVerbosity > 0)
+ {
+ Format(buf, sizeof(buf), " ({lightblue}%.2f{green}, {lightblue}%d{green} @ {lightblue}%d%%{green}",
+ g_PlayerStates[client][fPrestrafe], g_PlayerStates[client][nStrafes], RoundFloat(g_PlayerStates[client][fSync]));
+
+ StrCat(strOutput, sizeof(strOutput), buf);
+ }
+
+ if(g_PlayerStates[client][bBlockMode] && g_PlayerStates[client][fBlockDistance] != -1.0 && g_PlayerStates[client][fEdge] != -1.0)
+ {
+ Format(buf, sizeof(buf), ", edge: {lightblue}%.2f{default}", g_PlayerStates[client][fEdge]);
+
+ StrCat(strOutput, sizeof(strOutput), buf);
+ }
+
+ StrCat(strOutput, sizeof(strOutput), ")");
+
+ if(bPrintToAll)
+ {
+ CPrintToChatAll("%s", strOutput);
+ }
+ else
+ {
+ CPrintToChat(client, "%s", strOutput);
+ }
+ }
+ else
+ {
+ decl String:strOutput[512];
+
+ if(g_PlayerStates[client][fJumpDistance] < (g_PlayerStates[client][JumpType] == JT_LONGJUMP ? 265.0 : g_PlayerStates[client][JumpType] == JT_LADDERJUMP ? 155.0 : 285.0))
+ {
+ strcopy(strOutput, sizeof(strOutput), "{white}");
+ }
+ else if(g_PlayerStates[client][fJumpDistance] < (g_PlayerStates[client][JumpType] == JT_LONGJUMP ? 268.0 : g_PlayerStates[client][JumpType] == JT_LADDERJUMP ? 165.0 : 295.0))
+ {
+ strcopy(strOutput, sizeof(strOutput), "{green}");
+ }
+ else
+ {
+ strcopy(strOutput, sizeof(strOutput), "{red}");
+ }
+
+ decl String:strName[64];
+ GetClientName(client, strName, sizeof(strName));
+
+ Format(buf, sizeof(buf), "%s jumped %.2f units",
+ strName, g_PlayerStates[client][fJumpDistance]);
+
+ StrCat(strOutput, sizeof(strOutput), buf);
+
+ if(g_PlayerStates[client][JumpType])
+ {
+ Format(buf, sizeof(buf), " with %s%s",
+ g_PlayerStates[client][JumpType] == JT_BHOPJUMP && g_PlayerStates[client][bStamina] ? "easy" : "",
+ g_strJumpTypeLwr[g_PlayerStates[client][JumpType]]);
+
+ StrCat(strOutput, sizeof(strOutput), buf);
+ }
+
+ if(g_PlayerStates[client][JumpDir] != JD_FORWARDS)
+ {
+ if(g_PlayerStates[client][JumpDir] == JD_SIDEWAYS)
+ {
+ StrCat(strOutput, sizeof(strOutput), " sideways");
+ }
+ else if(g_PlayerStates[client][JumpDir] == JD_BACKWARDS)
+ {
+ StrCat(strOutput, sizeof(strOutput), " backwards");
+ }
+ }
+
+ if(!g_PlayerStates[client][bDuck] && !g_PlayerStates[client][bLastDuckState])
+ {
+ StrCat(strOutput, sizeof(strOutput), " no duck");
+ }
+
+ if(g_PlayerStates[client][bBlockMode])
+ {
+ if(g_PlayerStates[client][fBlockDistance] != -1.0)
+ {
+ Format(buf, sizeof(buf), " @ %.1f block%s", g_PlayerStates[client][fBlockDistance], g_PlayerStates[client][bFailedBlock] ? " (failed)" : "");
+
+ StrCat(strOutput, sizeof(strOutput), buf);
+ }
+ else if(g_PlayerStates[client][bFailedBlock])
+ {
+ StrCat(strOutput, sizeof(strOutput), " @ ? block (failed)");
+ }
+ }
+
+ StrCat(strOutput, sizeof(strOutput), "!");
+
+ if(g_nVerbosity > 2)
+ {
+ Format(buf, sizeof(buf), " (%.2f, %d @ %d%%, %d",
+ g_PlayerStates[client][fPrestrafe], g_PlayerStates[client][nStrafes], RoundFloat(g_PlayerStates[client][fSync]), RoundFloat(g_PlayerStates[client][fMaxSpeed]));
+
+ StrCat(strOutput, sizeof(strOutput), buf);
+ }
+ else if(g_nVerbosity > 1)
+ {
+ Format(buf, sizeof(buf), " (%.2f, %d @ %d%%",
+ g_PlayerStates[client][fPrestrafe], g_PlayerStates[client][nStrafes], RoundFloat(g_PlayerStates[client][fSync]));
+
+ StrCat(strOutput, sizeof(strOutput), buf);
+ }
+
+ if(g_PlayerStates[client][bBlockMode] && g_PlayerStates[client][fBlockDistance] != -1.0 && g_PlayerStates[client][fEdge] != -1.0)
+ {
+ Format(buf, sizeof(buf), ", edge: %.2f", g_PlayerStates[client][fEdge]);
+
+ StrCat(strOutput, sizeof(strOutput), buf);
+ }
+
+ StrCat(strOutput, sizeof(strOutput), ")");
+
+ if(bPrintToAll)
+ {
+ CPrintToChatAll("%s", strOutput);
+ }
+ else
+ {
+ CPrintToChat(client, "%s", strOutput);
+ }
+ }
+}
+
+
+///////////////////////////////////
+///////////////////////////////////
+//////// ////////
+//////// Trace functions ////////
+//////// ////////
+///////////////////////////////////
+///////////////////////////////////
+
+#define RAYTRACE_Z_DELTA -0.1
+#define GAP_TRACE_LENGTH 10000.0
+
+public bool:WorldFilter(entity, mask)
+{
+ if (entity >= 1 && entity <= MaxClients)
+ return false;
+
+ return true;
+}
+
+bool:TracePlayer(Float:vEndPos[3], Float:vNormal[3], const Float:vTraceOrigin[3], const Float:vEndPoint[3], bool:bCorrectError = true)
+{
+ new Float:vMins[3] = {-16.0, -16.0, 0.0}, Float:vMaxs[3] = {16.0, 16.0, 0.0};
+
+ TR_TraceHullFilter(vTraceOrigin, vEndPoint, vMins, vMaxs, MASK_PLAYERSOLID, WorldFilter);
+
+ if(!TR_DidHit()) // although tracehull does not ever seem to not hit (merely returning a hit at the end of the line), I'm keeping this here just in case, I guess
+ {
+ return false;
+ }
+
+ TR_GetEndPosition(vEndPos);
+ TR_GetPlaneNormal(INVALID_HANDLE, vNormal);
+
+ // correct slopes
+ if(vNormal[2])
+ {
+ vNormal[2] = 0.0;
+ NormalizeVector(vNormal, vNormal);
+ }
+
+ #if defined DEBUG
+ new Float:v1[3], Float:v2[3];
+ v1 = vEndPos;
+ v2 = vEndPos;
+
+ v1[0] += 16.0;
+ v1[1] += 16.0;
+ v2[0] += 16.0;
+ v2[1] -= 16.0;
+
+ CreateBeam2(v1, v2, 0, 255, 0);
+
+ v1[0] -= 32.0;
+ v1[1] -= 32.0;
+
+ CreateBeam2(v1, v2, 0, 255, 0);
+
+ v2[0] -= 32.0;
+ v2[1] += 32.0;
+
+ CreateBeam2(v1, v2, 0, 255, 0);
+
+ v1[0] += 32.0;
+ v1[1] += 32.0;
+
+ CreateBeam2(v1, v2, 0, 255, 0);
+ #endif
+
+ Adjust(vEndPos, vNormal);
+
+ // dunno where this error comes from
+ if(bCorrectError)
+ {
+ vEndPos[0] -= vNormal[0] * 0.03125;
+ vEndPos[1] -= vNormal[1] * 0.03125;
+ }
+
+ new Float:fDist = GetVectorDistance(vTraceOrigin, vEndPos);
+ return fDist != 0.0 && fDist < GetVectorDistance(vTraceOrigin, vEndPoint);
+}
+
+// no function overloading... @__@
+bool:TracePlayer2(Float:vEndPos[3], const Float:vTraceOrigin[3], const Float:vEndPoint[3], bool:bCorrectError = true)
+{
+ new Float:vNormal[3];
+
+ return TracePlayer(vEndPos, vNormal, vTraceOrigin, vEndPoint, bCorrectError);
+}
+
+bool:TraceRay(Float:vEndPos[3], Float:vNormal[3], const Float:vTraceOrigin[3], const Float:vEndPoint[3], bool:bCorrectError = true)
+{
+ TR_TraceRayFilter(vTraceOrigin, vEndPoint, MASK_PLAYERSOLID, RayType_EndPoint, WorldFilter);
+
+ if(!TR_DidHit())
+ {
+ return false;
+ }
+
+ TR_GetEndPosition(vEndPos);
+ TR_GetPlaneNormal(INVALID_HANDLE, vNormal);
+
+ // correct slopes
+ if(vNormal[2])
+ {
+ vNormal[2] = 0.0;
+ NormalizeVector(vNormal, vNormal);
+ }
+
+ if(bCorrectError)
+ {
+ vEndPos[0] -= vNormal[0] * 0.03125;
+ vEndPos[1] -= vNormal[1] * 0.03125;
+ }
+
+ new Float:fDist = GetVectorDistance(vTraceOrigin, vEndPos);
+ return fDist != 0.0 && fDist < GetVectorDistance(vTraceOrigin, vEndPoint);
+}
+
+bool:TraceRay2(Float:vEndPos[3], const Float:vTraceOrigin[3], const Float:vEndPoint[3], bool:bCorrectError = true)
+{
+ new Float:vNormal[3];
+
+ return TraceRay(vEndPos, vNormal, vTraceOrigin, vEndPoint, bCorrectError);
+}
+
+bool:IsLeft(const Float:vDir[3], const Float:vNormal[3])
+{
+ if(vNormal[1] > 0)
+ {
+ if(vDir[0] > vNormal[0])
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if(vDir[0] > vNormal[0])
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+}
+
+// align with normal
+Align(Float:vOut[3], const Float:v1[3], const Float:v2[3], const Float:vNormal[3])
+{
+ // cardinal
+ if(!vNormal[0] || !vNormal[1])
+ {
+ if(vNormal[0])
+ {
+ vOut[0] = v2[0];
+ vOut[1] = v1[1];
+ }
+ else
+ {
+ vOut[0] = v1[0];
+ vOut[1] = v2[1];
+ }
+
+ return;
+ }
+
+ // noncardinal
+ // rotate to cardinal, perform the same operation, rotate the result back
+
+ // [ cos(t) -sin(t) 0 ]
+ // Rz = [ sin(t) cos(t) 0 ]
+ // [ 0 0 1 ]
+
+ new Float:vTo[3] = {1.0, 0.0}, Float:fAngle = ArcCosine(GetVectorDotProduct(vNormal, vTo)), Float:fRotatedOriginY, Float:vRotatedEndPos[2];
+
+ if(IsLeft(vTo, vNormal))
+ {
+ fAngle = -fAngle;
+ }
+
+ fRotatedOriginY = v1[0] * Sine(fAngle) + v1[1] * Cosine(fAngle);
+
+ vRotatedEndPos[0] = v2[0] * Cosine(fAngle) - v2[1] * Sine(fAngle);
+ vRotatedEndPos[1] = fRotatedOriginY;
+
+ fAngle = -fAngle;
+
+ vOut[0] = vRotatedEndPos[0] * Cosine(fAngle) - vRotatedEndPos[1] * Sine(fAngle);
+ vOut[1] = vRotatedEndPos[0] * Sine(fAngle) + vRotatedEndPos[1] * Cosine(fAngle);
+}
+
+// Adjust collision hitbox center to periphery (the furthest point you could be from the edge as inferred by the normal)
+Adjust(Float:vOrigin[3], const Float:vNormal[3])
+{
+ // cardinal
+ if(!vNormal[0] || !vNormal[1])
+ {
+ vOrigin[0] -= vNormal[0] * 16.0;
+ vOrigin[1] -= vNormal[1] * 16.0;
+
+ return;
+ }
+
+ // noncardinal
+ // since the corner will always be the furthest point, set it to the corner of the normal's quadrant
+ if(vNormal[0] > 0.0)
+ {
+ vOrigin[0] -= 16.0;
+ }
+ else
+ {
+ vOrigin[0] += 16.0;
+ }
+
+ if(vNormal[1] > 0.0)
+ {
+ vOrigin[1] -= 16.0;
+ }
+ else
+ {
+ vOrigin[1] += 16.0;
+ }
+}
+
+Float:GetEdge(client)
+{
+ new Float:vOrigin[3], Float:vTraceOrigin[3], Float:vDir[3];
+ GetClientAbsOrigin(client, vOrigin);
+
+ GetEntPropVector(client, Prop_Data, "m_vecVelocity", vDir);
+
+ NormalizeVector(vDir, vDir);
+
+ vTraceOrigin = vOrigin;
+ vTraceOrigin[0] += vDir[0] * 64.0;
+ vTraceOrigin[1] += vDir[1] * 64.0;
+ vTraceOrigin[2] += RAYTRACE_Z_DELTA;
+
+ new Float:vEndPoint[3];
+ vEndPoint = vOrigin;
+ vEndPoint[0] -= vDir[0] * 16.0 * 1.414214;
+ vEndPoint[1] -= vDir[1] * 16.0 * 1.414214;
+ vEndPoint[2] += RAYTRACE_Z_DELTA;
+
+ new Float:vEndPos[3], Float:vNormal[3];
+ if(!TracePlayer(vEndPos, vNormal, vTraceOrigin, vEndPoint))
+ {
+ return -1.0;
+ }
+
+ #if defined DEBUG
+ CreateLightglow("0 255 0", vOrigin);
+ #endif
+
+ Adjust(vOrigin, vNormal);
+
+ #if defined DEBUG
+ CreateLightglow("255 255 255", vEndPos);
+ CreateLightglow("255 0 0", vOrigin);
+ #endif
+
+ Align(vEndPos, vOrigin, vEndPos, vNormal);
+
+ #if defined DEBUG
+ CreateLightglow("0 0 255", vEndPos);
+ #endif
+
+ // Correct Z -- the trace ray is a bit lower
+ vEndPos[2] = vOrigin[2];
+
+ return GetVectorDistance(vEndPos, vOrigin);
+}
+
+Float:GetBlockDistance(client)
+{
+ decl Float:vOrigin[3], Float:vTraceOrigin[3], Float:vDir[3], Float:vEndPoint[3];
+ GetClientAbsOrigin(client, vOrigin);
+
+ GetEntPropVector(client, Prop_Data, "m_vecVelocity", vDir);
+
+ NormalizeVector(vDir, vDir);
+
+ vTraceOrigin = vOrigin;
+ vTraceOrigin[0] += vDir[0] * 64.0;
+ vTraceOrigin[1] += vDir[1] * 64.0;
+ vTraceOrigin[2] += RAYTRACE_Z_DELTA;
+
+ vEndPoint = vOrigin;
+ vEndPoint[0] -= vDir[0] * 16.0 * 1.414214;
+ vEndPoint[1] -= vDir[1] * 16.0 * 1.414214;
+ vEndPoint[2] += RAYTRACE_Z_DELTA;
+
+ new Float:vBlockStart[3], Float:vNormal[3];
+ if(!TracePlayer(vBlockStart, vNormal, vTraceOrigin, vEndPoint))
+ {
+ return -1.0;
+ }
+
+ new Float:vBlockEnd[3];
+
+ Array_Copy(vNormal, g_PlayerStates[client][vBlockNormal], 2);
+
+ vEndPoint = vBlockStart;
+ vEndPoint[0] += vNormal[0] * 300.0;
+ vEndPoint[1] += vNormal[1] * 300.0;
+
+ if(TracePlayer2(vBlockEnd, vBlockStart, vEndPoint))
+ {
+ Array_Copy(vBlockEnd, g_PlayerStates[client][vBlockEndPos], 3);
+
+ Align(vBlockEnd, vBlockStart, vBlockEnd, vNormal);
+
+ if(vNormal[0] == 0.0 || vNormal[1] == 0.0)
+ {
+ return GetVectorDistance(vBlockStart, vBlockEnd);
+ }
+ else
+ {
+ return GetVectorDistance(vBlockStart, vBlockEnd) - 32.0 * (FloatAbs(vNormal[0]) + FloatAbs(vNormal[1]) - 1.0);
+ }
+ }
+ else
+ {
+ // Trace the other direction
+
+ // rotate normal da way opposite da direction
+ new bool:bLeft = IsLeft(vDir, vNormal);
+
+ vDir = vNormal;
+
+ new Float:fTempSwap = vDir[0];
+
+ vDir[0] = vDir[1];
+ vDir[1] = fTempSwap;
+
+ if(bLeft)
+ {
+ vDir[0] = -vDir[0];
+ }
+ else
+ {
+ vDir[1] = -vDir[1];
+ }
+
+ vTraceOrigin = vOrigin;
+ vTraceOrigin[0] += vDir[0] * 48.0;
+ vTraceOrigin[1] += vDir[1] * 48.0;
+ vTraceOrigin[2] += RAYTRACE_Z_DELTA;
+
+ vEndPoint = vTraceOrigin;
+ vEndPoint[0] += vNormal[0] * 300.0;
+ vEndPoint[1] += vNormal[1] * 300.0;
+
+ if(!TracePlayer2(vBlockEnd, vTraceOrigin, vEndPoint))
+ {
+ return -1.0;
+ }
+
+ Array_Copy(vBlockEnd, g_PlayerStates[client][vBlockEndPos], 3);
+
+ // adjust vBlockStart -- the second trace was on a different axis
+ Align(vBlockStart, vBlockStart, vBlockEnd, vNormal);
+
+ if(vNormal[0] == 0.0 || vNormal[1] == 0.0)
+ {
+ return GetVectorDistance(vBlockStart, vBlockEnd);
+ }
+ else
+ {
+ return GetVectorDistance(vBlockStart, vBlockEnd) - 32.0 * (FloatAbs(vNormal[0]) + FloatAbs(vNormal[1]) - 1.0);
+ }
+ }
+}
+
+bool:GetGapPoint(Float:vOut[3], Float:vNormal[3], client)
+{
+ decl Float:vAngles[3], Float:vTraceOrigin[3], Float:vDir[3], Float:vEndPoint[3];
+ GetClientEyePosition(client, vTraceOrigin);
+ GetClientEyeAngles(client, vAngles);
+
+ TBAnglesToUV(vDir, vAngles);
+
+ vEndPoint = vTraceOrigin;
+ vEndPoint[0] += vDir[0] * GAP_TRACE_LENGTH;
+ vEndPoint[1] += vDir[1] * GAP_TRACE_LENGTH;
+ vEndPoint[2] += vDir[2] * GAP_TRACE_LENGTH;
+
+ if(!TraceRay(vOut, vNormal, vTraceOrigin, vEndPoint))
+ {
+ return false;
+ }
+
+ #if defined DEBUG
+ CreateBeam(vTraceOrigin, vEndPoint);
+ #endif
+
+ return true;
+}
+
+bool:GetOppositePoint(Float:vOut[3], const Float:vTraceOrigin[3], const Float:vNormal[3])
+{
+ decl Float:vDir[3], Float:vEndPoint[3];
+
+ vDir = vNormal;
+
+ if(vDir[2])
+ {
+ vDir[2] = 0.0;
+ NormalizeVector(vDir, vDir);
+ }
+
+ vEndPoint = vTraceOrigin;
+ vEndPoint[0] += vDir[0] * 10000.0;
+ vEndPoint[1] += vDir[1] * 10000.0;
+
+ if(!TraceRay2(vOut, vTraceOrigin, vEndPoint))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+
+
+// generic utility functions
+
+Float:GetSpeed(client)
+{
+ new Float:vVelocity[3];
+ GetEntPropVector(client, Prop_Data, "m_vecVelocity", vVelocity);
+ vVelocity[2] = 0.0;
+
+ return GetVectorLength(vVelocity);
+}
+
+Float:GetVSpeed(const Float:v[3])
+{
+ new Float:vVelocity[3];
+ vVelocity = v;
+ vVelocity[2] = 0.0;
+
+ return GetVectorLength(vVelocity);
+}
+
+SendPanelMsg(client, const String:strFormat[], any:...)
+{
+ new Handle:hPanel = CreatePanel();
+
+ decl String:buf[512];
+
+ VFormat(buf, sizeof(buf), strFormat, 3);
+
+ SetPanelTitle(hPanel, buf);
+
+ SendPanelToClient(hPanel, client, EmptyPanelHandler, 10);
+
+ CloseHandle(hPanel);
+}
+
+DrawPanelTextF(Handle:hPanel, const String:strFormat[], any:...)
+{
+ decl String:buf[512];
+
+ VFormat(buf, sizeof(buf), strFormat, 3);
+
+ DrawPanelText(hPanel, buf);
+}
+
+Append(String:sOutput[], maxlen, const String:sFormat[], any:...)
+{
+ decl String:buf[1024];
+
+ VFormat(buf, sizeof(buf), sFormat, 4);
+
+ StrCat(sOutput, maxlen, buf);
+}
+
+// undefined for negative numbers
+Float:fmod(Float:a, Float:b)
+{
+ while(a > b)
+ a -= b;
+
+ return a;
+}
+
+stock Float:round(Float:a, b, Float:Base = 10.0)
+{
+ new Float:f = Pow(Base, float(b));
+ return RoundFloat(a * f) / f;
+}
+
+CreateBeamClient(client, const Float:v1[3], const Float:v2[3], r = 255, g = 255, b = 255, Float:fLifetime = 10.0)
+{
+ new color[4];
+ color[0] = r;
+ color[1] = g;
+ color[2] = b;
+ color[3] = 100;
+ TE_SetupBeamPoints(v1, v2, g_BeamModel, 0, 0, 0, fLifetime, 10.0, 10.0, 10, 0.0, color, 0);
+ TE_SendToClient(client);
+}
+
+#if defined DEBUG
+CreateLightglow(const String:sColor[], const Float:vOrigin[3])
+{
+ new Lightglow = CreateEntityByName("env_lightglow");
+ SetEntPropVector(Lightglow, Prop_Data, "m_vecOrigin", vOrigin);
+ DispatchKeyValue(Lightglow,"rendercolor", sColor);
+ DispatchKeyValue(Lightglow,"GlowProxySize", "5");
+ DispatchKeyValue(Lightglow,"VerticalGlowSize", "5");
+ DispatchKeyValue(Lightglow,"HorizontalGlowSize", "5");
+ DispatchSpawn(Lightglow);
+ CreateTimer(10.0, KillEntity, Lightglow);
+}
+
+CreateBeam(const Float:v1[3], const Float:v2[3])
+{
+ new color[4] = {255, 255, 255, 100};
+ TE_SetupBeamPoints(v1, v2, g_BeamModel, 0, 0, 0, 10.0, 3.0, 3.0, 10, 0.0, color, 0);
+ TE_SendToAll();
+}
+
+CreateBeam2(const Float:v1[3], const Float:v2[3], r, g, b)
+{
+ new color[4];
+ color[0] = r;
+ color[1] = g;
+ color[2] = b;
+ color[3] = 255;
+ TE_SetupBeamPoints(v1, v2, g_BeamModel, 0, 0, 0, 10.0, 10.0, 10.0, 10, 0.0, color, 0);
+ TE_SendToAll();
+}
+
+public Action:KillEntity(Handle:timer, any:entity)
+{
+ AcceptEntityInput(entity, "Kill");
+}
+#endif \ No newline at end of file
diff --git a/sourcemod-1.5-dev/scripting/spcomp.exe b/sourcemod-1.5-dev/scripting/spcomp.exe
new file mode 100644
index 0000000..9539647
--- /dev/null
+++ b/sourcemod-1.5-dev/scripting/spcomp.exe
Binary files differ