diff --git a/hypnonema.db b/hypnonema.db
index 498b87b36..af17a62ef 100644
Binary files a/hypnonema.db and b/hypnonema.db differ
diff --git a/resources/Fire-Script/whitelist.json b/resources/Fire-Script/whitelist.json
index 6dbcc3bfb..aa94f7298 100644
--- a/resources/Fire-Script/whitelist.json
+++ b/resources/Fire-Script/whitelist.json
@@ -1 +1 @@
-{"steam:110000112db6102":true,"steam:110000147619e76":true,"steam:110000131ff8eae":true,"steam:11000010e6980a7":true}
\ No newline at end of file
+{"steam:110000112db6102":true,"steam:110000147619e76":true,"steam:110000131ff8eae":true,"steam:11000010e6980a7":true,"steam:11000013c64f700":true}
\ No newline at end of file
diff --git a/resources/Interaction-Menu/.gitignore b/resources/Interaction-Menu/.gitignore
new file mode 100644
index 000000000..6fd0a376d
--- /dev/null
+++ b/resources/Interaction-Menu/.gitignore
@@ -0,0 +1,41 @@
+# Compiled Lua sources
+luac.out
+
+# luarocks build files
+*.src.rock
+*.zip
+*.tar.gz
+
+# Object files
+*.o
+*.os
+*.ko
+*.obj
+*.elf
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+*.def
+*.exp
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
diff --git a/resources/Interaction-Menu/LICENSE b/resources/Interaction-Menu/LICENSE
new file mode 100644
index 000000000..f288702d2
--- /dev/null
+++ b/resources/Interaction-Menu/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ 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.
+
+
+ Copyright (C)
+
+ 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 .
+
+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:
+
+ Copyright (C)
+ 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
+.
+
+ 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
+.
diff --git a/resources/Interaction-Menu/README.md b/resources/Interaction-Menu/README.md
new file mode 100644
index 000000000..eb98e6a91
--- /dev/null
+++ b/resources/Interaction-Menu/README.md
@@ -0,0 +1,30 @@
+[](https://semdevelopment.com/discord)
+
+# SEM_InteractionMenu
+*Multi Purpose FiveM Interaction Menu*
+
+This resource is a menu with actions for LEO, Fire and Civ including Vehicle Controls and Emotes!
+
+Each section has features that would be used by each of the professions, for example the LEO Menu has Cuff, Drag, Seat, etc.
+Some menu features also have commands out of ease during RP.
+
+SEM_InteractionMenu was created using NativeUI [LUA]
+
+
+### Information:
+Current Version: **v1.7.1**
+
+Changes: **• Fixes menu item skipping**
+
+**THIS UPDATE *ONLY* AFFECTS THE DEPENDENCY NATIVEUI - YOU CAN JUST UPDATE THAT FILE *(NO OTHER FILES WERE CHANGED!)***
+
+
+### Links:
+
+Support/Discord: [Click Here](https://semdevelopment.com/discord)
+
+Information: [Click Here](https://semdevelopment.com/releases/interactionmenu)
+
+Instruction/Docs: [Click here](https://semdevelopment.com/releases/interactionmenu/docs)
+
+*For full changes checkout [here](https://semdevelopment.com/releases/interactionmenu/docs/changelog)*
diff --git a/resources/Interaction-Menu/client.lua b/resources/Interaction-Menu/client.lua
new file mode 100644
index 000000000..12f8e1f6d
--- /dev/null
+++ b/resources/Interaction-Menu/client.lua
@@ -0,0 +1,898 @@
+--[[
+──────────────────────────────────────────────────────────────
+
+ SEM_InteractionMenu (client.lua) - Created by Scott M
+ Current Version: v1.7.1 (Sep 2021)
+
+ Support: https://semdevelopment.com/discord
+
+ !!! Change vaules in the 'config.lua' !!!
+ DO NOT EDIT THIS IF YOU DON'T KNOW WHAT YOU ARE DOING
+
+──────────────────────────────────────────────────────────────
+]]
+
+
+
+--Cuffing Event
+local isCuffed = false
+RegisterNetEvent('SEM_InteractionMenu:Cuff')
+AddEventHandler('SEM_InteractionMenu:Cuff', function()
+ local Ped = PlayerPedId()
+ if (DoesEntityExist(Ped)) then
+ Citizen.CreateThread(function()
+ RequestAnimDict('mp_arresting')
+ while not HasAnimDictLoaded('mp_arresting') do
+ Citizen.Wait(0)
+ end
+
+ if isCuffed then
+ isCuffed = false
+ Citizen.Wait(500)
+ SetEnableHandcuffs(Ped, false)
+ ClearPedTasksImmediately(Ped)
+ else
+ isCuffed = true
+ SetEnableHandcuffs(Ped, true)
+ TaskPlayAnim(Ped, 'mp_arresting', 'idle', 8.0, -8, -1, 49, 0, 0, 0, 0)
+ end
+ end)
+ end
+end)
+
+--Cuff Animation & Restructions
+Citizen.CreateThread(function()
+ while true do
+ Citizen.Wait(1)
+
+ if isCuffed then
+ if not IsEntityPlayingAnim(GetPlayerPed(PlayerId()), 'mp_arresting', 'idle', 3) then
+ TaskPlayAnim(GetPlayerPed(PlayerId()), 'mp_arresting', 'idle', 8.0, -8, -1, 49, 0, 0, 0, 0)
+ end
+
+ SetCurrentPedWeapon(PlayerPedId(), 'weapon_unarmed', true)
+
+ if not Config.VehEnterCuffed then
+ DisableControlAction(1, 23, true) --F | Enter Vehicle
+ DisableControlAction(1, 75, true) --F | Exit Vehicle
+ end
+ DisableControlAction(1, 140, true) --R
+ DisableControlAction(1, 141, true) --Q
+ DisableControlAction(1, 142, true) --LMB
+ SetPedPathCanUseLadders(GetPlayerPed(PlayerId()), false)
+ if IsPedInAnyVehicle(GetPlayerPed(PlayerId()), false) then
+ DisableControlAction(0, 59, true) --Vehicle Driving
+ end
+ end
+ end
+end)
+
+
+
+--Dragging Event
+local Drag = false
+local OfficerDrag = -1
+RegisterNetEvent('SEM_InteractionMenu:Drag')
+AddEventHandler('SEM_InteractionMenu:Drag', function(ID)
+ Drag = not Drag
+ OfficerDrag = ID
+
+ if not Drag then
+ DetachEntity(PlayerPedId(), true, false)
+ end
+end)
+
+--Drag Attachment
+Citizen.CreateThread(function()
+ while true do
+ Citizen.Wait(1)
+
+ if Drag then
+ local Ped = GetPlayerPed(GetPlayerFromServerId(OfficerDrag))
+ local Ped2 = PlayerPedId()
+ AttachEntityToEntity(Ped2, Ped, 4103, 0.35, 0.38, 0.0, 0.0, 0.0, 0.0, false, false, false, false, 2, true)
+ DisableControlAction(1, 140, true) --R
+ DisableControlAction(1, 141, true) --Q
+ DisableControlAction(1, 142, true) --LMB
+ end
+ end
+end)
+
+
+
+--Force Seat Player Event
+RegisterNetEvent('SEM_InteractionMenu:Seat')
+AddEventHandler('SEM_InteractionMenu:Seat', function(Veh)
+ local Pos = GetEntityCoords(PlayerPedId())
+ local EntityWorld = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0.0, 20.0, 0.0)
+ local RayHandle = CastRayPointToPoint(Pos.x, Pos.y, Pos.z, EntityWorld.x, EntityWorld.y, EntityWorld.z, 10, PlayerPedId(), 0)
+ local _, _, _, _, VehicleHandle = GetRaycastResult(RayHandle)
+ if VehicleHandle ~= nil then
+ SetPedIntoVehicle(PlayerPedId(), VehicleHandle, 1)
+ end
+end)
+
+
+
+--Force Unseat Player Event
+RegisterNetEvent('SEM_InteractionMenu:Unseat')
+AddEventHandler('SEM_InteractionMenu:Unseat', function(ID)
+ local Ped = GetPlayerPed(ID)
+ ClearPedTasksImmediately(Ped)
+ PlayerPos = GetEntityCoords(PlayerPedId(), true)
+ local X = PlayerPos.x - 0
+ local Y = PlayerPos.y - 0
+
+ SetEntityCoords(PlayerPedId(), X, Y, PlayerPos.z)
+end)
+
+
+
+--Spike Strip Spawn Event
+local SpawnedSpikes = {}
+RegisterNetEvent('SEM_InteractionMenu:Spikes-SpawnSpikes')
+AddEventHandler('SEM_InteractionMenu:Spikes-SpawnSpikes', function(Length)
+ if IsPedInAnyVehicle(PlayerPedId(), false) then
+ Notify('~r~You can\'t set spikes while in a vehicle!')
+ return
+ end
+
+ local SpawnCoords = GetOffsetFromEntityInWorldCoords(GetPlayerPed(PlayerId()) , 0.0, 2.0, 0.0)
+ for a = 1, Length do
+ local Spike = CreateObject(GetHashKey('P_ld_stinger_s'), SpawnCoords.x, SpawnCoords.y, SpawnCoords.z, 1, 1, 1)
+ local NetID = NetworkGetNetworkIdFromEntity(Spike)
+ SetNetworkIdExistsOnAllMachines(NetID, true)
+ SetNetworkIdCanMigrate(NetID, false)
+ SetEntityHeading(Spike, GetEntityHeading(GetPlayerPed(PlayerId()) ))
+ PlaceObjectOnGroundProperly(Spike)
+ FreezeEntityPosition(Spike, true)
+ SpawnCoords = GetOffsetFromEntityInWorldCoords(Spike, 0.0, 4.0, 0.0)
+ table.insert(SpawnedSpikes, NetID)
+ end
+end)
+
+--Spike Strip Delete Event
+RegisterNetEvent('SEM_InteractionMenu:Spikes-DeleteSpikes')
+AddEventHandler('SEM_InteractionMenu:Spikes-DeleteSpikes', function()
+ for a = 1, #SpawnedSpikes do
+ local Spike = NetworkGetEntityFromNetworkId(SpawnedSpikes[a])
+ DeleteEntity(Spike)
+ end
+ Notify('~r~Spikes Strips Removed!')
+ SpawnedSpikes = {}
+end)
+
+--Spike Strip Tire Popping
+Citizen.CreateThread(function()
+ while true do
+ Citizen.Wait(25)
+
+ if IsPedInAnyVehicle(PlayerPedId() , false) then
+ local Vehicle = GetVehiclePedIsIn(PlayerPedId() , false)
+
+ if GetPedInVehicleSeat(Vehicle, -1) == PlayerPedId() then
+ local VehiclePos = GetEntityCoords(Vehicle, false)
+ local Spike = GetClosestObjectOfType(VehiclePos.x, VehiclePos.y, VehiclePos.z, 2.0, GetHashKey('P_ld_stinger_s'), 1, 1, 1)
+
+ if Spike ~= 0 then
+ local Tires = {
+ {bone = 'wheel_lf', index = 0},
+ {bone = 'wheel_rf', index = 1},
+ {bone = 'wheel_lm', index = 2},
+ {bone = 'wheel_rm', index = 3},
+ {bone = 'wheel_lr', index = 4},
+ {bone = 'wheel_rr', index = 5}
+ }
+
+ for a = 1, #Tires do
+ local TirePos = GetWorldPositionOfEntityBone(Vehicle, GetEntityBoneIndexByName(Vehicle, Tires[a].bone))
+ local Spike = GetClosestObjectOfType(TirePos.x, TirePos.y, TirePos.z, 2.0, GetHashKey('P_ld_stinger_s'), 1, 1, 1)
+ local SpikePos = GetEntityCoords(Spike, false)
+ local Distance = Vdist(TirePos.x, TirePos.y, TirePos.z, SpikePos.x, SpikePos.y, SpikePos.z)
+
+ if Distance < 1.8 then
+ if not IsVehicleTyreBurst(Vehicle, Tires[a].index, true) or IsVehicleTyreBurst(Vehicle, Tires[a].index, false) then
+ SetVehicleTyreBurst(Vehicle, Tires[a].index, false, 1000.0)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end)
+
+
+
+--Backup
+RegisterNetEvent('SEM_InteractionMenu:CallBackup')
+AddEventHandler('SEM_InteractionMenu:CallBackup', function(Code, StreetName, Coords)
+ if LEORestrict() then
+ local BackupBlip = nil
+ local BackupBlips = {}
+
+ local function CreateBlip(x, y, z, Name, Sprite, Size, Colour)
+ BackupBlip = AddBlipForCoord(x, y, z)
+ SetBlipSprite(BackupBlip, Sprite)
+ SetBlipDisplay(BackupBlip, 4)
+ SetBlipScale(BackupBlip, Size)
+ SetBlipColour(BackupBlip, Colour)
+ SetBlipAsShortRange(BackupBlip, true)
+
+ BeginTextCommandSetBlipName('STRING')
+ AddTextComponentString(Name)
+ EndTextCommandSetBlipName(BackupBlip)
+ table.insert(BackupBlips, BackupBlip)
+ Citizen.Wait(Config.BackupBlipTimeout * 60000)
+ for _, Blip in pairs(BackupBlips) do
+ RemoveBlip(Blip)
+ end
+ end
+
+ if Code == 1 then
+ Notify('An officer is requesting ~g~Code 1 ~w~backup at ~b~' .. StreetName)
+ CreateBlip(Coords.x, Coords.y, Coords.z, 'Code 1 Backup Requested', 56, 0.8, 2)
+ elseif Code == 2 then
+ Notify('An officer is requesting ~y~Code 2 ~w~backup at ~b~' .. StreetName)
+ CreateBlip(Coords.x, Coords.y, Coords.z, 'Code 2 Backup Requested', 56, 0.8, 17)
+ elseif Code == 3 then
+ Notify('An officer is requesting ~r~Code 3 ~w~backup at ~b~' .. StreetName)
+ CreateBlip(Coords.x, Coords.y, Coords.z, 'Code 3 Backup Requested', 56, 1.0, 49)
+ elseif Code == 99 then
+ Notify('An officer is requesting ~r~Code 99 ~w~backup at ~b~' .. StreetName)
+ CreateBlip(Coords.x, Coords.y, Coords.z, 'Code 99 Backup Requested', 56, 1.2, 49)
+ elseif Code == 'panic' then
+ Notify('An officer has pressed their ~r~Panic Button ~w~at ~b~' .. StreetName)
+ CreateBlip(Coords.x, Coords.y, Coords.z, 'Panic Button Pressed', 103, 1.2, 49)
+ end
+ end
+end)
+
+
+
+--Jail
+CurrentlyJailed = false
+EarlyRelease = false
+OriginalJailTime = 0
+RegisterNetEvent('SEM_InteractionMenu:JailPlayer')
+AddEventHandler('SEM_InteractionMenu:JailPlayer', function(JailTime)
+ if CurrentlyJailed then
+ return
+ end
+ if CurrentlyHospitaled then
+ return
+ end
+
+ OriginalJailTime = JailTime
+
+ local Ped = PlayerPedId()
+ if DoesEntityExist(Ped) then
+ Citizen.CreateThread(function()
+ SetEntityCoords(Ped, Config.JailLocation.Jail.x, Config.JailLocation.Jail.y, Config.JailLocation.Jail.z)
+ SetEntityHeading(Ped, Config.JailLocation.Jail.h)
+ CurrentlyJailed = true
+
+ while JailTime >= 0 and not EarlyRelease do
+ SetEntityInvincible(Ped, true)
+ if IsPedInAnyVehicle(Ped, false) then
+ ClearPedTasksImmediately(Ped)
+ end
+
+ if JailTime % 30 == 0 and JailTime ~= 0 then
+ TriggerEvent('chat:addMessage', {
+ multiline = true,
+ color = {86, 96, 252},
+ args = {'Judge', JailTime .. ' months until release.'},
+ })
+ end
+
+ Citizen.Wait(1000)
+
+ local Location = GetEntityCoords(Ped, true)
+ local Distance = Vdist(Config.JailLocation.Jail.x, Config.JailLocation.Jail.y, Config.JailLocation.Jail.z, Location['x'], Location['y'], Location['z'])
+ if Distance > 100 then
+ SetEntityCoords(Ped, Config.JailLocation.Jail.x, Config.JailLocation.Jail.y, Config.JailLocation.Jail.z)
+ SetEntityHeading(Ped, Config.JailLocation.Jail.h)
+ TriggerEvent('chat:addMessage', {
+ multiline = true,
+ color = {86, 96, 252},
+ args = {'Judge', 'Don\'t try escape, its impossible'},
+ })
+ end
+
+ JailTime = JailTime - 1
+ end
+
+ if EarlyRelease then
+ TriggerServerEvent('SEM_InteractionMenu:GlobalChat', {86, 96, 252}, 'Judge', GetPlayerName(PlayerId()) .. ' was released from Jail on Parole')
+ else
+ TriggerServerEvent('SEM_InteractionMenu:GlobalChat', {86, 96, 252}, 'Judge', GetPlayerName(PlayerId()) .. ' was released from Jail after ' .. OriginalJailTime .. ' months(s).')
+ end
+ SetEntityCoords(Ped, Config.JailLocation.Release.x, Config.JailLocation.Release.y, Config.JailLocation.Release.z)
+ SetEntityHeading(Ped, Config.JailLocation.Release.h)
+ CurrentlyJailed = false
+ EarlyRelease = false
+ end)
+ end
+end)
+
+RegisterNetEvent('SEM_InteractionMenu:UnjailPlayer')
+AddEventHandler('SEM_InteractionMenu:UnjailPlayer', function()
+ EarlyRelease = true
+end)
+
+
+
+--Toggle LEO Weapons
+CarbineEquipped = false
+ShotgunEquipped = false
+Citizen.CreateThread(function()
+ while true do
+ Citizen.Wait(50)
+
+ if Config.UnrackWeapons == 1 then
+ local Ped = PlayerPedId()
+ local CurrentWeapon = GetSelectedPedWeapon(Ped)
+
+ if CarbineEquipped then
+ SetCurrentPedWeapon(Ped, 'weapon_carbinerifle', true)
+ else
+ if tostring(CurrentWeapon) == '-2084633992' then
+ Notify('~o~You need to unrack your rifle before you can use it')
+ SetCurrentPedWeapon(Ped, 'weapon_unarmed', true)
+ end
+ end
+
+ if ShotgunEquipped then
+ SetCurrentPedWeapon(Ped, 'weapon_pumpshotgun', true)
+ else
+ if tostring(CurrentWeapon) == '487013001' then
+ Notify('~o~You need to unrack your shotgun before you can use it')
+ SetCurrentPedWeapon(Ped, 'weapon_unarmed', true)
+ end
+ end
+ end
+ end
+end)
+
+
+
+--Civilian Adverts
+RegisterNetEvent('SEM_InteractionMenu:SyncAds')
+AddEventHandler('SEM_InteractionMenu:SyncAds',function(Text, Name, Loc, File, ID)
+ Ad(Text, Name, Loc, File, ID)
+end)
+
+
+
+--Inventory
+RegisterNetEvent('SEM_InteractionMenu:InventoryResult')
+AddEventHandler('SEM_InteractionMenu:InventoryResult', function(Inventory)
+ Citizen.Wait(5000)
+
+ if Inventory == nil then
+ Inventory = 'Empty'
+ end
+
+ Notify('~b~Inventory Items: ~g~' .. Inventory)
+end)
+
+
+
+--BAC
+RegisterNetEvent('SEM_InteractionMenu:BACResult')
+AddEventHandler('SEM_InteractionMenu:BACResult', function(BACLevel)
+ Citizen.Wait(5000)
+
+ if BACLevel == nil then
+ BACLevel = 0.00
+ end
+
+ if tonumber(BACLevel) < 0.08 then
+ Notify('~b~BAC Level: ~g~' .. tostring(BACLevel))
+ else
+ Notify('~b~BAC Level: ~r~' .. tostring(BACLevel))
+ end
+end)
+
+
+
+
+--Hospital
+CurrentlyHospitalized = false
+EarlyDischarge = false
+OriginalHospitalTime = 0
+RegisterNetEvent('SEM_InteractionMenu:HospitalizePlayer')
+AddEventHandler('SEM_InteractionMenu:HospitalizePlayer', function(HospitalTime, HospitalLocation)
+ if CurrentlyHospitaled then
+ return
+ end
+ if CurrentlyJailed then
+ return
+ end
+
+ OriginalHospitalTime = HospitalTime
+
+ local Ped = PlayerPedId()
+ if DoesEntityExist(Ped) then
+ Citizen.CreateThread(function()
+ SetEntityCoords(Ped, HospitalLocation.Hospital.x, HospitalLocation.Hospital.y, HospitalLocation.Hospital.z)
+ SetEntityHeading(Ped, HospitalLocation.Hospital.h)
+ CurrentlyHospitaled = true
+
+ while HospitalTime >= 0 and not EarlyDischarge do
+ SetEntityInvincible(Ped, true)
+ if IsPedInAnyVehicle(Ped, false) then
+ ClearPedTasksImmediately(Ped)
+ end
+
+ if HospitalTime % 30 == 0 and HospitalTime ~= 0 then
+ TriggerEvent('chat:addMessage', {
+ multiline = true,
+ color = {86, 96, 252},
+ args = {'Doctor', HospitalTime .. ' months until release.'},
+ })
+ end
+
+ Citizen.Wait(1000)
+
+ local Location = GetEntityCoords(Ped, true)
+ local Distance = Vdist(HospitalLocation.Hospital.x, HospitalLocation.Hospital.y, HospitalLocation.Hospital.z, Location['x'], Location['y'], Location['z'])
+ if Distance > 30 then
+ SetEntityCoords(Ped, HospitalLocation.Hospital.x, HospitalLocation.Hospital.y, HospitalLocation.Hospital.z)
+ SetEntityHeading(Ped, HospitalLocation.Hospital.h)
+ TriggerEvent('chat:addMessage', {
+ multiline = true,
+ color = {86, 96, 252},
+ args = {'Doctor', 'You cannot discharge yourself!'},
+ })
+ end
+
+ HospitalTime = HospitalTime - 1
+ end
+
+ if EarlyDischarge then
+ TriggerServerEvent('SEM_InteractionMenu:GlobalChat', {86, 96, 252}, 'Doctor', GetPlayerName(PlayerId()) .. ' was discharged from Hospital early')
+ else
+ TriggerServerEvent('SEM_InteractionMenu:GlobalChat', {86, 96, 252}, 'Doctor', GetPlayerName(PlayerId()) .. ' was discharged from Hospital after ' .. OriginalHospitalTime .. ' months(s).')
+ end
+ SetEntityCoords(Ped, HospitalLocation.Release.x, HospitalLocation.Release.y, HospitalLocation.Release.z)
+ SetEntityHeading(Ped, HospitalLocation.Release.h)
+ CurrentlyHospitaled = false
+ EarlyDischarge = false
+ end)
+ end
+end)
+
+RegisterNetEvent('SEM_InteractionMenu:UnhospitalizePlayer')
+AddEventHandler('SEM_InteractionMenu:UnhospitalizePlayer', function()
+ EarlyDischarge = true
+end)
+
+
+
+--Station Blips
+Citizen.CreateThread(function()
+ if Config.DisplayStationBlips then
+ local function CreateBlip(x, y, z, Name, Colour, Sprite)
+ StationBlip = AddBlipForCoord(x, y, z)
+ SetBlipSprite(StationBlip, Sprite)
+ if Config.StationBlipsDispalyed == 1 then
+ SetBlipDisplay(StationBlip, 3)
+ elseif Config.StationBlipsDispalyed == 2 then
+ SetBlipDisplay(StationBlip, 5)
+ else
+ SetBlipDisplay(StationBlip, 2)
+ end
+ SetBlipScale(StationBlip, 1.0)
+ SetBlipColour(StationBlip, Colour)
+ SetBlipAsShortRange(StationBlip, true)
+
+ BeginTextCommandSetBlipName('STRING')
+ AddTextComponentString(Name)
+ EndTextCommandSetBlipName(StationBlip)
+ end
+
+ for _, Station in pairs(Config.LEOStations) do
+ CreateBlip(Station.coords.x, Station.coords.y, Station.coords.z, 'Police Station', 38, 60)
+ end
+ for _, Station in pairs(Config.FireStations) do
+ CreateBlip(Station.coords.x, Station.coords.y, Station.coords.z, 'Fire Station', 1, 60)
+ end
+ for _, Station in pairs(Config.HospitalStations) do
+ CreateBlip(Station.coords.x, Station.coords.y, Station.coords.z, 'Hospital', 2, 61)
+ end
+ end
+end)
+
+
+
+--Permissions
+LEOAce = false
+TriggerServerEvent('SEM_InteractionMenu:LEOPerms')
+RegisterNetEvent('SEM_InteractionMenu:LEOPermsResult')
+AddEventHandler('SEM_InteractionMenu:LEOPermsResult', function(Allowed)
+ if Allowed then
+ LEOAce = true
+ else
+ LEOAce = false
+ end
+end)
+
+FireAce = false
+TriggerServerEvent('SEM_InteractionMenu:FirePerms')
+RegisterNetEvent('SEM_InteractionMenu:FirePermsResult')
+AddEventHandler('SEM_InteractionMenu:FirePermsResult', function(Allowed)
+ if Allowed then
+ FireAce = true
+ else
+ FireAce = false
+ end
+end)
+
+UnjailAllowed = false
+TriggerServerEvent('SEM_InteractionMenu:UnjailPerms')
+RegisterNetEvent('SEM_InteractionMenu:UnjailPermsResult')
+AddEventHandler('SEM_InteractionMenu:UnjailPermsResult', function(Allowed)
+ if Allowed then
+ UnjailAllowed = true
+ else
+ UnjailAllowed = false
+ end
+end)
+
+UnhospitalAllowed = false
+TriggerServerEvent('SEM_InteractionMenu:UnhospitalPerms')
+RegisterNetEvent('SEM_InteractionMenu:UnhospitalPermsResult')
+AddEventHandler('SEM_InteractionMenu:UnhospitalPermsResult', function(Allowed)
+ if Allowed then
+ UnhospitalAllowed = true
+ else
+ UnhospitalAllowed = false
+ end
+end)
+
+
+
+--Emote
+Citizen.CreateThread(function()
+ while true do
+ Citizen.Wait(1)
+
+ if EmotePlaying then
+ if Config.EmoteHelp then
+ NotifyHelp('You are playing an Emote, ~b~Move to Cancel')
+ end
+
+ -- Spacebar W S A D
+ if (IsControlPressed(0, 22) or IsControlPressed(0, 32) or IsControlPressed(0, 33) or IsControlPressed(0, 34) or IsControlPressed(0, 35)) then
+ CancelEmote()
+ end
+ end
+ end
+end)
+
+
+
+--Commands
+Citizen.CreateThread(function()
+ if EmoteRestrict() then
+ local Index = 0
+ local Emotes = ''
+ for _, Emote in pairs(Config.EmotesList) do
+ Index = Index + 1
+ if Index == 1 then
+ Emotes = Emotes .. Emote.name
+ else
+ Emotes = Emotes .. ', ' .. Emote.name
+ end
+ end
+
+ TriggerEvent('chat:addSuggestion', '/emotes', 'List of Current Avaliable Emotes')
+ TriggerEvent('chat:addSuggestion', '/emote', 'Play Emote', {{name = 'Emote Name', help = 'Emotes: ' .. Emotes}})
+ else
+ TriggerEvent('chat:removeSuggestion', '/emotes')
+ TriggerEvent('chat:removeSuggestion', '/emote')
+ end
+
+ TriggerEvent('chat:addSuggestion', '/eng', 'Toggles Engine')
+ TriggerEvent('chat:addSuggestion', '/hood', 'Toggles Vehicle\'s Hood')
+ TriggerEvent('chat:addSuggestion', '/trunk', 'Toggles Vehicle\'s Trunk')
+ TriggerEvent('chat:addSuggestion', '/clear', 'Clears all Weapons')
+ TriggerEvent('chat:addSuggestion', '/cuff', 'Cuff Player', {{name = 'ID', help = 'Players Server ID'}})
+ TriggerEvent('chat:addSuggestion', '/drag', 'Drag Player', {{name = 'ID', help = 'Players Server ID'}})
+ TriggerEvent('chat:addSuggestion', '/dropweapon', 'Drops Weapon in Hand')
+ TriggerEvent('chat:addSuggestion', '/loadout', 'Equips LEO Weapon Loadout')
+ TriggerEvent('chat:addSuggestion', '/coords', 'Shows Current Player Coords and Heading')
+
+ if Config.Radar ~= 0 then
+ TriggerEvent('chat:addSuggestion', '/radar', 'Toggle Radar Menu')
+ end
+
+ if Config.LEOAccess == 3 or Config.FireAccess == 3 then
+ if Config.OndutyPSWDActive then
+ TriggerEvent('chat:addSuggestion', '/onduty', 'Enable LEO/Fire Menu', {{name = 'Department', help = 'LEO or Fire'}, {name = 'Password', help = 'Onduty Password'}})
+ else
+ TriggerEvent('chat:addSuggestion', '/onduty', 'Enable LEO/Fire Menu', {{name = 'Department', help = 'LEO or Fire'}})
+ end
+ else
+ TriggerEvent('chat:removeSuggestion', '/onduty')
+ end
+end)
+
+LEOOnduty = false
+FireOnduty = false
+RegisterCommand('onduty', function(source, args, rawCommand)
+ if Config.LEOAccess == 3 or Config.FireAccess == 3 then
+ if Config.OndutyPSWDActive then
+ if args[2] == Config.OndutyPSWD then
+ local Department = args[1]:lower()
+ if Department == 'leo' then
+ LEOOnduty = not LEOOnduty
+ if LEOOnduty then
+ Notify('~g~You are onduty as an LEO')
+ else
+ Notify('~o~You are no longer onduty as an LEO')
+ end
+ elseif Department == 'fire' then
+ FireOnduty = not FireOnduty
+ if FireOnduty == true then
+ Notify('~g~You are onduty as an Firefighter')
+ else
+ Notify('~o~You are no longer onduty as an Firefighter')
+ end
+ else
+ Notify('~r~Invalid Department!')
+ end
+ else
+ Notify('~r~Incorrect Password')
+ end
+ else
+ local Department = args[1]:lower()
+ if Department == 'leo' then
+ LEOOnduty = not LEOOnduty
+ if LEOOnduty then
+ Notify('~g~You are onduty as an LEO')
+ else
+ Notify('~o~You are no longer onduty as an LEO')
+ end
+ elseif Department == 'fire' then
+ FireOnduty = not FireOnduty
+ if FireOnduty == true then
+ Notify('~g~You are onduty as an Firefighter')
+ else
+ Notify('~o~You are no longer onduty as an Firefighter')
+ end
+ else
+ Notify('~r~Invalid Department!')
+ end
+ end
+ end
+end)
+
+function IsOndutyLEO()
+ return LEOOnduty
+end
+function IsOndutyFire()
+ return FireOnduty
+end
+
+RegisterCommand('cuff', function(source, args, rawCommand)
+ if LEORestrict() or FireRestrict() then
+ if args[1] ~= nil then
+ local ID = tonumber(args[1])
+ if Config.CommandDistanceChecked then
+ if GetDistance(source) < Config.CommandDistance then
+ TriggerServerEvent('SEM_InteractionMenu:CuffNear', ID)
+ else
+ Notify('~r~That player is too far away')
+ end
+ else
+ TriggerServerEvent('SEM_InteractionMenu:CuffNear', ID)
+ end
+ else
+ TriggerServerEvent('SEM_InteractionMenu:CuffNear', GetClosestPlayer())
+ end
+ else
+ Notify('~r~Insufficient Permissions')
+ end
+end)
+
+RegisterCommand('drag', function(source, args, rawCommand)
+ if LEORestrict() or FireRestrict() then
+ if args[1] ~= nil then
+ local ID = tonumber(args[1])
+ if Config.CommandDistanceChecked then
+ if GetDistance(source) < Config.CommandDistance then
+ TriggerServerEvent('SEM_InteractionMenu:DragNear', ID)
+ else
+ Notify('~r~That player is too far away')
+ end
+ else
+ TriggerServerEvent('SEM_InteractionMenu:DragNear', ID)
+ end
+ else
+ TriggerServerEvent('SEM_InteractionMenu:DragNear', GetClosestPlayer())
+ end
+ else
+ Notify('~r~Insufficient Permissions')
+ end
+end)
+
+RegisterCommand('radar', function(source, args, rawCommand)
+ if Config.Radar ~= 0 then
+ if LEORestrict() or FireRestrict() then
+ ToggleRadar()
+ else
+ Notify('~r~Insufficient Permissions')
+ end
+ end
+end)
+
+RegisterCommand('loadout', function(source, args, rawCommand)
+ if LEORestrict() then
+ if args[1] then
+ local RequestedLoadout = args[1]
+
+ for Name, Loadout in pairs(Config.LEOLoadouts) do
+ if Name:lower() == RequestedLoadout:lower() then
+ SetEntityHealth(GetPlayerPed(-1), 200)
+ RemoveAllPedWeapons(GetPlayerPed(-1), true)
+ AddArmourToPed(GetPlayerPed(-1), 100)
+
+ for _, Weapon in pairs(Loadout) do
+ GiveWeapon(Weapon.weapon)
+
+ for _, Component in pairs(Weapon.components) do
+ AddWeaponComponent(Weapon.weapon, Component)
+ end
+ end
+ return
+ end
+ end
+
+ Notify('~r~Invalid Loadout')
+ else
+ SetEntityHealth(PlayerPedId(), 200)
+ RemoveAllPedWeapons(PlayerPedId(), true)
+ AddArmourToPed(PlayerPedId(), 100)
+ GiveWeapon('weapon_nightstick')
+ GiveWeapon('weapon_flashlight')
+ GiveWeapon('weapon_fireextinguisher')
+ GiveWeapon('weapon_flare')
+ GiveWeapon('weapon_stungun')
+ GiveWeapon('weapon_combatpistol')
+ AddWeaponComponent('weapon_combatpistol', 'component_at_pi_flsh')
+ Notify('~g~Loadout Spawned')
+ end
+ else
+ Notify('~r~You aren\'t an LEO')
+ end
+end)
+
+RegisterCommand('hu', function(source, args, rawCommand)
+ local Ped = PlayerPedId()
+ if DoesEntityExist(Ped) and not HandCuffed then
+ Citizen.CreateThread(function()
+ LoadAnimation('random@mugging3')
+ if IsEntityPlayingAnim(Ped, 'random@mugging3', 'handsup_standing_base', 3) or HandCuffed then
+ ClearPedSecondaryTask(Ped)
+ SetEnableHandcuffs(Ped, false)
+ elseif not IsEntityPlayingAnim(Ped, 'random@mugging3', 'handsup_standing_base', 3) or not HandCuffed then
+ TaskPlayAnim(Ped, 'random@mugging3', 'handsup_standing_base', 8.0, -8, -1, 49, 0, 0, 0, 0)
+ SetEnableHandcuffs(Ped, true)
+ end
+ end)
+ end
+end)
+
+RegisterCommand('huk', function(source, args, rawCommand)
+ local Ped = PlayerPedId()
+ if (DoesEntityExist(Ped) and not IsEntityDead(Ped)) and not HandCuffed then
+ Citizen.CreateThread(function()
+ LoadAnimation('random@arrests')
+ if (IsEntityPlayingAnim(Ped, 'random@arrests', 'kneeling_arrest_idle', 3)) then
+ TaskPlayAnim(Ped, 'random@arrests', 'kneeling_arrest_get_up', 8.0, 1.0, -1, 128, 0, 0, 0, 0)
+ else
+ TaskPlayAnim(Ped, 'random@arrests', 'idle_2_hands_up', 8.0, 1.0, -1, 2, 0, 0, 0, 0)
+ Wait (4000)
+ TaskPlayAnim(Ped, 'random@arrests', 'kneeling_arrest_idle', 8.0, 1.0, -1, 2, 0, 0, 0, 0)
+ end
+ end)
+ end
+end)
+
+RegisterCommand('dropweapon', function(source, args, rawCommand)
+ local CurrentWeapon = GetSelectedPedWeapon(PlayerPedId())
+ SetPedDropsInventoryWeapon(PlayerPedId(), CurrentWeapon, -2.0, 0.0, 0.5, 30)
+ Notify('~r~Weapon Dropped!')
+end)
+
+RegisterCommand('clear', function(source, args, rawCommand)
+ SetEntityHealth(PlayerPedId(), 200)
+ RemoveAllPedWeapons(PlayerPedId(), true)
+ Notify('~r~All Weapons Cleared!')
+end)
+
+RegisterCommand('eng', function(source, args, rawCommand)
+ local Veh = GetVehiclePedIsIn(PlayerPedId(), false)
+ if Veh ~= nil and Veh ~= 0 and GetPedInVehicleSeat(Veh, 0) then
+ SetVehicleEngineOn(Veh, (not GetIsVehicleEngineRunning(Veh)), false, true)
+ Notify('~g~Engine Toggled!')
+ end
+end)
+
+RegisterCommand('hood', function(source, args, rawCommand)
+ local Veh = GetVehiclePedIsIn(PlayerPedId(), false)
+
+ if Veh ~= nil and Veh ~= 0 and Veh ~= 1 then
+ if GetVehicleDoorAngleRatio(Veh, 4) > 0 then
+ SetVehicleDoorShut(Veh, 4, false)
+ else
+ SetVehicleDoorOpen(Veh, 4, false, false)
+ end
+ end
+
+ Notify('~g~Hood Toggled!')
+end)
+
+RegisterCommand('trunk', function(source, args, rawCommand)
+ local Veh = GetVehiclePedIsIn(PlayerPedId(), false)
+
+ if Veh ~= nil and Veh ~= 0 and Veh ~= 1 then
+ if GetVehicleDoorAngleRatio(Veh, 5) > 0 then
+ SetVehicleDoorShut(Veh, 5, false)
+ else
+ SetVehicleDoorOpen(Veh, 5, false, false)
+ end
+ end
+
+ Notify('~g~Trunk Toggled!')
+end)
+
+RegisterCommand('emotes', function(source, args, rawCommand)
+ if EmoteRestrict() then
+ local Index = 0
+ local Emotes = ''
+ for _, Emote in pairs(Config.EmotesList) do
+ Index = Index + 1
+ if Index == 1 then
+ Emotes = Emotes .. Emote.name
+ else
+ Emotes = Emotes .. ', ' .. Emote.name
+ end
+ end
+
+ TriggerEvent('chat:addMessage', {
+ multiline = true,
+ color = {255, 0 ,0},
+ args = {'Emotes', '\n^r^7' .. Emotes},
+ })
+ end
+end)
+
+RegisterCommand('emote', function(source, args, rawCommand)
+ if EmoteRestrict() then
+ local SelectedEmote = args[1]
+
+ for _, Emote in pairs(Config.EmotesList) do
+ if Emote.name == SelectedEmote then
+ PlayEmote(Emote.emote, Emote.name)
+ return
+ end
+ end
+
+ TriggerEvent('chat:addMessage', {
+ multiline = true,
+ color = {255, 0, 0},
+ args = {'Emotes', 'Invalid Emote!'},
+ })
+ end
+end)
+
+RegisterCommand('coords', function(source, args, rawCommand)
+ local Coords = GetEntityCoords(PlayerPedId())
+ local Heading = GetEntityHeading(PlayerPedId())
+
+ TriggerEvent('chatMessage', 'Coords', {255, 255, 0}, '\nX: ' .. Coords.x .. '\nY: ' .. Coords.y .. '\nZ: ' .. Coords.z .. '\nHeading: ' .. Heading)
+end)
diff --git a/resources/Interaction-Menu/config.lua b/resources/Interaction-Menu/config.lua
new file mode 100644
index 000000000..99ad89db5
--- /dev/null
+++ b/resources/Interaction-Menu/config.lua
@@ -0,0 +1,615 @@
+--[[
+───────────────────────────────────────────────────────────────
+
+ SEM_InteractionMenu (config.lua) - Created by Scott M
+ Current Version: v1.7.1 (Sep 2021)
+
+ Support: https://semdevelopment.com/discord
+
+───────────────────────────────────────────────────────────────
+]]
+
+
+
+Config = {}
+
+
+
+---------------------------------------------------------------
+-- --
+-- Menu Features --
+-- --
+---------------------------------------------------------------
+
+--This is how the version check will be displayed in the server console
+--Full = 0 [Default] | Simple = 1 | Disabled = 2
+Config.VersionChecker = 1
+
+--This is how you open the menu either via a command or button
+--Button = 0 [Default] | Command = 1
+Config.OpenMenu = 0
+
+--This is the button that will open the menu (If chosen at Config.OpenMenu)
+--Default = 244 [M] | To change the button check out https://docs.fivem.net/game-references/controls/
+--Controller Support for this resource is DISABLED!
+Config.MenuButton = 166
+
+--This is the command that will open the menu (If chosen at Config.OpenMenu)
+Config.Command = 'policemenu'
+
+--This is the width of the menu when open
+--Default = 80
+Config.MenuWidth = 80
+
+--This is the position of the menu when open
+--Left = 0 [Default] | Right = 1
+Config.MenuOrientation = 0
+
+--This is the title of the menu dispalyed
+--Default = The default title of the menu is 'Interaction Menu'
+--Player Name = This is the name of the player
+--Custom = This is a custom title set by you at Config.MenuTitleCustom
+--Default = 0 [Default] | Player Name = 1 | Custom = 2
+Config.MenuTitle = 0
+
+--This is the custom title you can set for the menu (If chosen at Config.MenuTitle)
+Config.MenuTitleCustom = 'Custom Menu Title'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---------------------------------------------------------------
+-- --
+-- General/Shared Features --
+-- --
+---------------------------------------------------------------
+
+--This determines if the onduty password is active, if false the password will NOT be required when doing the command
+Config.OndutyPSWDActive = false
+
+--This is the onduty password, only people with the password can access the menu if chosen at Config.LEOAccess/Config.FireAccess
+Config.OndutyPSWD = 'OndutyPSWD'
+
+--This determines if the distance between the player using the command and the person being cuffed/dragged is checked
+Config.CommandDistanceChecked = true
+
+--This determines how close you need to be to cuff/drag someone using their ID
+--Default = 50
+Config.CommandDistance = 50
+
+--This determines if the stations section of the LEO & Fire menu will be visible
+--Station Locations can be set at Config.LEOStations & Config.FireStations
+Config.ShowStations = true
+
+--This determines if the stations menu will have a teleport section, if set to false ONLY the waypoint option will be visible
+Config.AllowStationTeleport = true
+
+--This determines if the stations set in the Config.LEOStations & Config.FireStations have blips on the map
+Config.DisplayStationBlips = true
+
+--This sets where the station blips will be displayed (Mini Map / Main Map)
+--On Mini Map & Main Map = 0 [Default] | Only on Main Map = 1 | Only on Mini Map = 2
+Config.StationBlipsDispalyed = 0
+
+--These are the props avaliable via the LEO & Fire menus
+Config.Props = {
+ --[[
+ EXAMPLE:
+ {name = 'a', spawncode = 'b'},
+ ────────────────────────────────────────────────────────────────
+ 'a' is the title that shows in the menu
+ 'b' is the spawn code for prop that will be spawned
+ ]]
+ {name = 'Police Barrier', spawncode = 'prop_barrier_work05'},
+ {name = 'Barrier', spawncode = 'prop_barrier_work06a'},
+ {name = 'Traffic Cone', spawncode = 'prop_roadcone01a'},
+ {name = 'Cone', spawncode = 'prop_roadcone02b'},
+ {name = 'Work Barrier', spawncode = 'prop_mp_barrier_02b'},
+ {name = 'Work Barrier 2', spawncode = 'prop_barrier_work01a'},
+ {name = 'Lighting', spawncode = 'prop_worklight_03b'},
+ {name = 'Tent', spawncode = 'prop_gazebo_02'},
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---------------------------------------------------------------
+-- --
+-- LEO Features --
+-- --
+---------------------------------------------------------------
+
+--This sets who can access the LEO menu
+--!!! NOTE: If LEO Peds is selected then onlys peds from the Config.LEOUniforms will have access to the menu
+--Disabled = 0 | Everyone = 1 [Default] | LEO Peds = 2 | Onduty Command = 3 | Ace Permissions = 4
+Config.LEOAccess = 1
+
+--This determines if the radar button will be displayed
+--NOTE: Wraith Radar is the ONLY radar script that works with the menu at the moment (This also includes any editied version) - Both his old and new radar are compatiable, link below
+--[[
+ Links:
+ WraithRS | Advanced Radar System: https://forum.cfx.re/t/release-wraithrs-advanced-radar-system-1-0-2/48543
+ Ascaped Plate Reader Edit: https://forum.cfx.re/t/release-edit-wraithrs-new-plate-reader/147269
+
+ Wraith ARS 2X Radar & Plate Reader: https://forum.cfx.re/t/release-wraith-ars-2x-police-radar-and-plate-reader-v1-2-4/1058277
+
+ **Other modified version of these resoruce should work**
+]]
+--Disabled = 0 [Default] | Wraith ARS 2x = 1 | WraithRS = 2
+Config.Radar = 0
+
+--This determines when someone if cuffed if they can enter or exit a vehicle
+Config.VehEnterCuffed = false
+
+--This determines if you need to unrack the carbine rifle of pumpshotun from a vehicle to obtain it
+--Disabled = 0 | Constant = 1 | Free-hand = 2 [Default]
+--Constant = Once unracked it is unable to be removed from hand until racked again in a vehicle
+--Free-hand = Once unracked it is able to be removed from hand
+Config.UnrackWeapons = 2
+
+--This sets if the Jail functions will be visible in the menu
+Config.LEOJail = true
+
+--This is the max time that someone can be jailed for (Seconds)
+Config.MaxJailTime = 300
+
+--These is the location of the jail and release point
+Config.JailLocation = {
+ Jail = {x = 1675.28, y = 2648.55, z = 45.56, h = 49.50},
+ Release = {x = 1851.24, y = 2585.77, z = 45.67, h = 271.44},
+}
+
+--This determines if the backup section of the LEO menu will be visible
+Config.DisplayBackup = true
+
+--This sets the time between the blip being created and removed (Minutes)
+--Default = 5
+Config.BackupBlipTimeout = 5
+
+--This determines if the LEO props menu will be available
+Config.DisplayProps = true
+
+--These are the station available via the station menu
+Config.LEOStations = {
+ {name = 'Sandy Shores', coords = {x = 1850.04, y = 3679.36, z = 34.26 , h = 208.84}},
+ {name = 'Paleto Bay', coords = {x = -438.51, y = 6017.93, z = 31.49 , h = 352.90}},
+
+ {name = 'Mission Row', coords = {x = 432.08, y = -985.25, z = 30.71 , h = 44.02}},
+ {name = 'Davis', coords = {x = 373.99, y = -1607.59, z = 29.29 , h = 192.15}},
+ {name = 'Vinewood', coords = {x = 638.03, y = -1.85, z = 82.78 , h = 290.18}},
+ {name = 'Vespucci', coords = {x = -1090.87, y = -807.29, z = 19.26 , h = 64.92}},
+
+ {name = 'NOOSE Headquarters', coords = {x = 2504.29, y = -384.11, z = 94.12, h = 264.01}},
+}
+
+--This determines if the LEO Unfiroms section will be visible
+Config.DisplayLEOUniforms = true
+
+--These are the LEO uniforms that are available via the loadouts - these will also be the uniforms which will give access to the LEO menu if that option if chosen at Config.LEOAccess
+Config.LEOUniforms = {
+ --[[
+ EXAMPLE:
+ {name = 'a', spawncode = 'b'},
+ ────────────────────────────────────────────────────────────────
+ 'a' is the title that shows in the menu
+ 'b' is the spawn code for uniform that will be spawned
+ ]]
+ {name = 'LSPD', spawncode = 's_m_y_cop_01'},
+ {name = 'BCSO', spawncode = 's_m_y_sheriff_01'},
+ {name = 'SAHP', spawncode = 's_m_y_hwaycop_01'},
+ {name = 'SWAT', spawncode = 's_m_y_swat_01'},
+ {name = 'Undercover', spawncode = 's_m_m_ciasec_01'},
+}
+
+--This determines if the LEO Loadouts section will be visible
+Config.DisplayLEOLoadouts = true
+
+--These are the weapon loadouts available via the loadouts
+Config.LEOLoadouts = {
+ --[[
+ EXAMPLE:
+ a = {
+ {weapon = 'b', components = 'c', 'c'},
+ },
+ ────────────────────────────────────────────────────────────────
+ 'a' is the title of the Loadout
+ 'b' is the weapon which you want to be added [A link to weapon names can be found below]
+ 'c' is the components which you want to be added to the weapon [A link to available weapon components can be found below]
+
+ Weapon Names https://forum.fivem.net/t/list-of-weapon-spawn-names-after-hours/90750
+ Weapon Components https://wiki.rage.mp/index.php?title=Weapons_Components
+ ]]
+ ['Standard'] = {
+ {weapon = 'weapon_flashlight', components = {''}},
+ {weapon = 'weapon_combatpistol', components = {'component_at_pi_flsh'}},
+ {weapon = 'weapon_stungun', components = {''}},
+ {weapon = 'weapon_carbinerifle', components = {'component_at_ar_flsh', 'component_at_scope_medium', 'component_at_ar_afgrip'}},
+ {weapon = 'weapon_pumpshotgun', components = {'component_at_ar_flsh'}},
+ {weapon = 'weapon_fireextinguisher', components = {''}},
+ {weapon = 'weapon_flare', components = {''}},
+ },
+
+ ['SWAT'] = {
+ {weapon = 'weapon_flashlight', components = {''}},
+ {weapon = 'weapon_combatpistol', components = {'component_at_pi_flsh'}},
+ {weapon = 'weapon_stungun', components = {''}},
+ {weapon = 'weapon_smg', components = {'component_at_ar_flsh', 'component_ar_scope_macro_02'}},
+ {weapon = 'weapon_carbinerifle', components = {'component_at_ar_flsh', 'component_at_scope_medium', 'component_at_ar_afgrip'}},
+ {weapon = 'weapon_pumpshotgun', components = {'component_at_ar_flsh'}},
+ {weapon = 'weapon_sniperrifle', components = {'comonent_at_scope_max'}},
+ {weapon = 'weapon_bzgas', components = {''}},
+ {weapon = 'weapon_fireextinguisher', components = {''}},
+ {weapon = 'weapon_flare', components = {''}},
+ }
+}
+
+--This determines if the LEO vehicles section if available
+Config.ShowLEOVehicles = true
+
+--This determines if the vehicle spawn codes are displayed next to the name
+Config.ShowLEOSpawnCode = true
+
+--These are the LEO vehicles which are avaiable via the menu
+Config.LEOVehiclesCategories = {
+ --[[
+ EXAMPLE:
+ ['a'] = {
+ {name = 'b', spawncode = 'c', livery = d, extras = {e, e}},
+ }
+ ────────────────────────────────────────────────────────────────
+ 'a' is the title of the Category
+ 'b' is the title of the vehicle that shows in the menu
+ 'c' is the spawn code for vehicle that will be spawned
+ d is the number of the livery which you want it to spawn with
+ e is the number(s) of extra(s) which you want it to spawn with
+
+ **NOTE: Sometimes the sections do NOT display if the order in the config below**
+ ]]
+
+ ['Police'] = {
+ {name = 'Police', spawncode = 'police'},
+ {name = 'Police', spawncode = 'police2'},
+ {name = 'Police', spawncode = 'police3'},
+ },
+
+ ['Sheriff'] = {
+ {name = 'Sheriff', spawncode = 'sheriff'},
+ {name = 'Sheriff', spawncode = 'sheriff2'},
+ },
+
+ ['Unmarked'] = {
+ {name = 'Unmarked', spawncode = 'police4'},
+ },
+}
+
+--This determines if the ai traffic manager will can accessible
+Config.DisplayTrafficManager = true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---------------------------------------------------------------
+-- --
+-- Fire Features --
+-- --
+---------------------------------------------------------------
+
+--This sets who can access the Fire menu
+--!!! NOTE: If Fire Peds is selected then onlys peds from the Config.FireUniforms will have access to the menu
+--Disabled = 0 | Everyone = 1 [Default] | Fire Peds = 2 | Onduty Command = 3 | Ace Permissions = 4
+Config.FireAccess = 1
+
+--This sets if the Hospitalize functions will be visible in the menu
+Config.FireHospital = true
+
+--This is the max time that someone can be hospitalized for (Seconds)
+Config.MaxHospitalTime = 300
+
+--These is the location of the hospital and release point
+--I would recommend using a MLO Interior/Ymap for the hospital
+Config.HospitalLocation = {
+ ['Pillbox Hill'] = {
+ Hospital = {x = 358.34, y = -589.98, z = 28.79, h = 257.19},
+ Release = {x = 372.78, y = -595.04, z = 28.84, h = 248.29},
+ },
+ ['Paleto Bay'] = {
+ Hospital = {x = -247.34, y = 6332.39, z = 32.42 , h = 226.90},
+ Release = {x = -247.34, y = 6332.39, z = 32.42 , h = 226.90},
+ }
+}
+
+--These are the station available via the station menu
+Config.FireStations = {
+ {name = 'Sandy Shores', coords = {x = 1693.57, y = 3582.68, z = 35.62 , h = 227.29}},
+ {name = 'Paleto Bay', coords = {x = -382.50, y = 6116.76, z = 31.47 , h = 7.29}},
+
+ {name = 'Davis', coords = {x = 201.16, y = -1631.67, z = 29.75, h = 296.67}},
+ {name = 'Rockford Hill', coords = {x = -636.47, y = -117.02, z = 38.02, h = 79.64}},
+ {name = 'El Burro Heights', coords = {x = 1191.83, y = -1461.74, z = 34.88, h = 329.54}},
+}
+
+--These are the locations of hospitals avaiable via the hospital menu
+Config.HospitalStations = {
+ {name = 'Sandy Shores', coords = {x = 1839.13, y = 3673.26, z = 34.27 , h = 210.83}},
+ {name = 'Paleto Bay', coords = {x = -247.34, y = 6332.39, z = 32.42 , h = 226.90}},
+
+ {name = 'Pillbox', coords = {x = 357.19, y = -593.46, z = 28.78, h = 260.70}},
+ {name = 'Davis', coords = {x = 294.59, y = -1448.17, z = 29.96, h = 320.92}},
+}
+
+--This determines if the LEO Unfiroms section will be visible
+Config.DisplayFireUniforms = true
+
+--These are the Fire uniforms that are available via the loadouts - these will also be the uniforms which will give access to the Fire menu if that option if chosen at Config.FireAccess
+Config.FireUniforms = {
+ --[[
+ EXAMPLE:
+ {name = 'a', spawncode = 'b'},
+ ────────────────────────────────────────────────────────────────
+ 'a' is the title that shows in the menu
+ 'b' is the spawn code for uniform that will be spawned
+ ]]
+ {name = 'Firefighter', spawncode = 's_m_y_fireman_01'},
+ {name = 'Paramedic', spawncode = 's_m_m_paramedic_01'},
+}
+
+--This determines if the LEO Loadouts section will be visible
+Config.DisplayFireLoadouts = true
+
+--This determines if the Fire vehicles section if available
+Config.ShowFireVehicles = true
+
+--This determines if the vehicle spawn codes are displayed next to the name
+Config.ShowFireSpawnCode = true
+
+--These are the Fire vehicles which are avaiable via the menu
+Config.FireVehicles = {
+ --[[
+ EXAMPLE:
+ {name = 'a', spawncode = 'b', livery = c, extras = {d, d}},
+ ────────────────────────────────────────────────────────────────
+ 'a' is the title of the vehicle that shows in the menu
+ 'b' is the spawn code for vehicle that will be spawned
+ 'c' is the number of the livery which you want it to spawn with
+ 'd' is the number(s) of extra(s) which you want it to spawn with
+
+ **NOTE: Sometimes the sections do NOT display if the order in the config below**
+ ]]
+
+ --These are the Vehicles that will show in the Category and there spawn codes
+ {name = 'Fire Engine', spawncode = 'firetruk'},
+ {name = 'Ambulance', spawncode = 'ambulance'},
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---------------------------------------------------------------
+-- --
+-- Civilian Features --
+-- --
+---------------------------------------------------------------
+
+--This sets who can access the Civlian menu
+--!!! NOTE: If Fire Peds is selected then onlys peds from the Config.FireUniforms will have access to the menu
+--Disabled = 0 | Everyone = 1 [Default]
+Config.CivAccess = 1
+
+--This determines if the Civilian vehicles section if available
+Config.ShowCivVehicles = true
+
+--This determines if the vehicle spawn codes are displayed next to the name
+Config.ShowCivSpawnCode = true
+
+--These are the Civilian vehicles which are avaiable via the menu
+Config.CivVehicles = {
+ --[[
+ EXAMPLE:
+ {name = 'a', spawncode = 'b'},
+ ────────────────────────────────────────────────────────────────
+ 'a' is the title of the vehicle that shows in the menu
+ 'b' is the spawn code for vehicle that will be spawned
+ ]]
+
+ --These are the Vehicles that will show in the Category and there spawn codes
+ {name = 'Adder', spawncode = 'adder'},
+ {name = 'Baller', spawncode = 'baller'},
+}
+
+--This determines if the civilian adverts sections of the menu if visible
+--NOTE: When someone sends an advert it will display the company name and then "Advertisement ##", this is the Server ID of the person that sent the advert
+Config.ShowCivAdverts = true
+
+--These are the adverts that are avaiable via the ads menu
+--NOTE: You can add additional adverts from https://wiki.gtanet.work/index.php?title=Notification_Pictures
+Config.CivAdverts = {
+ --[[
+ EXAMPLE:
+ {name = 'a', loc = 'b', file = 'c'},
+ ────────────────────────────────────────────────────────────────
+ 'a' is the title of the Adverts
+ 'b' is the location for the Advert's Image
+ 'c' is the file name for the Advert's Image
+ ]]
+
+
+
+ -- !!!!! Wouldn't Recommend Changing These Unless You Know What You're Doing !!!!!
+ -- !!!!! Wouldn't Recommend Changing These Unless You Know What You're Doing !!!!!
+ -- !!!!! Wouldn't Recommend Changing These Unless You Know What You're Doing !!!!!
+
+ {name = '24/7', loc = 'CHAR_FLOYD', file = '247'},
+ {name = 'Ammunation', loc = 'CHAR_AMMUNATION', file = 'CHAR_AMMUNATION'},
+ {name = 'Bugstars', loc = 'CHAR_BUGSTARS', file = 'CHAR_BUGSTARS'},
+ {name = 'Cluckin\' Bell', loc = 'CHAR_FLOYD', file = 'BELL'},
+ {name = 'Downtown Cab Co.', loc = 'CHAR_TAXI', file = 'CHAR_TAXI'},
+ {name = 'Dynasty 8', loc = 'CHAR_FLOYD', file = 'D8'},
+ {name = 'Fleeca Bank', loc = 'CHAR_BANK_FLEECA', file = 'CHAR_BANK_FLEECA'},
+ {name = 'Gruppe6', loc = 'CHAR_FLOYD', file = 'GRUPPE6'},
+ {name = 'Merry Weather', loc = 'CHAR_MP_MERRYWEATHER', file = 'CHAR_MP_MERRYWEATHER'},
+ {name = 'Limited Gasoline', loc = 'CHAR_FLOYD', file = 'LTD'},
+ {name = 'Liquor Ace', loc = 'CHAR_FLOYD', file = 'ACE'},
+ {name = 'Smoke on the Water', loc = 'CHAR_FLOYD', file = 'SOTW'},
+ {name = 'Pegasus', loc = 'CHAR_PEGASUS_DELIVERY', file = 'CHAR_PEGASUS_DELIVERY'},
+ {name = 'Los Santos Customs', loc = 'CHAR_LS_CUSTOMS', file = 'CHAR_LS_CUSTOMS'},
+ {name = 'Los Santos Traffic Info', loc = 'CHAR_LS_TOURIST_BOARD', file = 'CHAR_LS_TOURIST_BOARD'},
+ {name = 'Los Santos Water and Power', loc = 'CHAR_FLOYD', file = 'LSWP'},
+ {name = 'Mors Mutual Insurance', loc = 'CHAR_MP_MORS_MUTUAL', file = 'CHAR_MP_MORS_MUTUAL'},
+ {name = 'PostOP', loc = 'CHAR_FLOYD', file = 'OP'},
+ {name = 'Vanilla Unicorn', loc = 'CHAR_MP_STRIPCLUB_PR', file = 'CHAR_MP_STRIPCLUB_PR'},
+ {name = 'Weazel News', loc = 'CHAR_FLOYD', file = 'NEWS'},
+ {name = 'Facebook', loc = 'CHAR_FACEBOOK', file = 'CHAR_FACEBOOK'},
+ {name = 'Life Invader', loc = 'CHAR_LIFEINVADER', file = 'CHAR_LIFEINVADER'},
+ {name = 'YouTube', loc = 'CHAR_YOUTUBE', file = 'CHAR_YOUTUBE'},
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---------------------------------------------------------------
+-- --
+-- Vehicle Features --
+-- --
+---------------------------------------------------------------
+
+--This sets when players can access the vehicle menu
+--Disabled = 0 | All the Time = 1 [Default] | When in Vehicle = 2
+Config.VehicleAccess = 1
+
+--This determines if the vehicle options are avaiable, these include: Fix, Clean, Delete
+Config.VehicleOptions = true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---------------------------------------------------------------
+-- --
+-- Emote Features --
+-- --
+---------------------------------------------------------------
+
+--This sets which players can access the emote menu
+--Disabled = 0 | Everyone = 1 [Default]
+Config.EmoteAccess = 1
+
+--This sets if a help message is displayed when playing an emote
+Config.EmoteHelp = true
+
+--These are the emotes avaiable via the menu and the '/emotes' & '/emote [Emote]' commands
+Config.EmotesList = {
+ {name = 'binoculars', emote = 'WORLD_HUMAN_BINOCULARS'},
+ {name = 'camera', emote = 'WORLD_HUMAN_PAPARAZZI'},
+ {name = 'clean', emote = 'WORLD_HUMAN_MAID_CLEAN'},
+ {name = 'clipboard', emote = 'WORLD_HUMAN_CLIPBOARD'},
+ {name = 'coffee', emote = 'WORLD_HUMAN_AA_COFFEE'},
+ {name = 'cheer', emote = 'WORLD_HUMAN_CHEERING'},
+ {name = 'cop', emote = 'WORLD_HUMAN_COP_IDLES'},
+ {name = 'film', emote = 'WORLD_HUMAN_MOBILE_FILM_SHOCKING'},
+ {name = 'fish', emote = 'WORLD_HUMAN_STAND_FISHING'},
+ {name = 'flex', emote = 'WORLD_HUMAN_MUSCLE_FLEX'},
+ {name = 'guard', emote = 'WORLD_HUMAN_GUARD_STAND'},
+ {name = 'hammer', emote = 'WORLD_HUMAN_HAMMERING'},
+ {name = 'homeless', emote = 'WORLD_HUMAN_BUM_FREEWAY'},
+ {name = 'impatient', emote = 'WORLD_HUMAN_STAND_IMPATIENT'},
+ {name = 'jog', emote = 'WORLD_HUMAN_JOG_STANDING'},
+ {name = 'kneel', emote = 'CODE_HUMAN_MEDIC_KNEEL'},
+ {name = 'lean', emote = 'WORLD_HUMAN_LEANING'},
+ {name = 'mechanic', emote = 'WORLD_HUMAN_VEHICLE_MECHANIC'},
+ {name = 'medic', emote = 'CODE_HUMAN_MEDIC_TEND_TO_DEAD'},
+ {name = 'music', emote = 'WORLD_HUMAN_MUSICIAN'},
+ {name = 'notepad', emote = 'CODE_HUMAN_MEDIC_TIME_OF_DEATH'},
+ {name = 'party', emote = 'WORLD_HUMAN_PARTYING'},
+ {name = 'phone', emote = 'WORLD_HUMAN_STAND_MOBILE'},
+ {name = 'phonecall', emote = 'WORLD_HUMAN_STAND_MOBILE_UPRIGHT'},
+ {name = 'selfie', emote = 'WORLD_HUMAN_TOURIST_MOBILE'},
+ {name = 'sit', emote = 'WORLD_HUMAN_PICNIC'},
+ {name = 'sleep', emote = 'WORLD_HUMAN_BUM_SLUMPED'},
+ {name = 'smoke', emote = 'WORLD_HUMAN_SMOKING'},
+ {name = 'statue', emote = 'WORLD_HUMAN_HUMAN_STATUE'},
+ {name = 'stupor', emote = 'WORLD_HUMAN_STUPOR'},
+ {name = 'sunbathe', emote = 'WORLD_HUMAN_SUNBATHE'},
+ {name = 'sunbathe2', emote = 'WORLD_HUMAN_SUNBATHE_BACK'},
+ {name = 'traffic', emote = 'WORLD_HUMAN_CAR_PARK_ATTENDANT'},
+ {name = 'weed', emote = 'WORLD_HUMAN_SMOKING_POT'},
+ {name = 'weights', emote = 'WORLD_HUMAN_MUSCLE_FREE_WEIGHTS'},
+ {name = 'weld', emote = 'WORLD_HUMAN_WELDING'},
+ {name = 'yoga', emote = 'WORLD_HUMAN_YOGA'},
+}
diff --git a/resources/Interaction-Menu/dependencies/NativeUI.lua b/resources/Interaction-Menu/dependencies/NativeUI.lua
new file mode 100644
index 000000000..f574b20bd
--- /dev/null
+++ b/resources/Interaction-Menu/dependencies/NativeUI.lua
@@ -0,0 +1,3884 @@
+UIResRectangle = setmetatable({}, UIResRectangle)
+UIResRectangle.__index = UIResRectangle
+UIResRectangle.__call = function() return "Rectangle" end
+
+UIResText = setmetatable({}, UIResText)
+UIResText.__index = UIResText
+UIResText.__call = function() return "Text" end
+
+Sprite = setmetatable({}, Sprite)
+Sprite.__index = Sprite
+Sprite.__call = function() return "Sprite" end
+
+UIMenuItem = setmetatable({}, UIMenuItem)
+UIMenuItem.__index = UIMenuItem
+UIMenuItem.__call = function() return "UIMenuItem", "UIMenuItem" end
+
+UIMenuCheckboxItem = setmetatable({}, UIMenuCheckboxItem)
+UIMenuCheckboxItem.__index = UIMenuCheckboxItem
+UIMenuCheckboxItem.__call = function() return "UIMenuItem", "UIMenuCheckboxItem" end
+
+UIMenuListItem = setmetatable({}, UIMenuListItem)
+UIMenuListItem.__index = UIMenuListItem
+UIMenuListItem.__call = function() return "UIMenuItem", "UIMenuListItem" end
+
+UIMenuSliderItem = setmetatable({}, UIMenuSliderItem)
+UIMenuSliderItem.__index = UIMenuSliderItem
+UIMenuSliderItem.__call = function() return "UIMenuItem", "UIMenuSliderItem" end
+
+UIMenuColouredItem = setmetatable({}, UIMenuColouredItem)
+UIMenuColouredItem.__index = UIMenuColouredItem
+UIMenuColouredItem.__call = function() return "UIMenuItem", "UIMenuColouredItem" end
+
+UIMenuProgressItem = setmetatable({}, UIMenuProgressItem)
+UIMenuProgressItem.__index = UIMenuProgressItem
+UIMenuProgressItem.__call = function() return "UIMenuItem", "UIMenuProgressItem" end
+
+UIMenuHeritageWindow = setmetatable({}, UIMenuHeritageWindow)
+UIMenuHeritageWindow.__index = UIMenuHeritageWindow
+UIMenuHeritageWindow.__call = function() return "UIMenuWindow", "UIMenuHeritageWindow" end
+
+UIMenuGridPanel = setmetatable({}, UIMenuGridPanel)
+UIMenuGridPanel.__index = UIMenuGridPanel
+UIMenuGridPanel.__call = function() return "UIMenuPanel", "UIMenuGridPanel" end
+
+UIMenuColourPanel = setmetatable({}, UIMenuColourPanel)
+UIMenuColourPanel.__index = UIMenuColourPanel
+UIMenuColourPanel.__call = function() return "UIMenuPanel", "UIMenuColourPanel" end
+
+UIMenuPercentagePanel = setmetatable({}, UIMenuPercentagePanel)
+UIMenuPercentagePanel.__index = UIMenuPercentagePanel
+UIMenuPercentagePanel.__call = function() return "UIMenuPanel", "UIMenuPercentagePanel" end
+
+UIMenu = setmetatable({}, UIMenu)
+UIMenu.__index = UIMenu
+UIMenu.__call = function() return "UIMenu" end
+
+MenuPool = setmetatable({}, MenuPool)
+MenuPool.__index = MenuPool
+
+NativeUI = {}
+
+CharacterMap = { [' '] = 6, ['!'] = 6, ['"'] = 6, ['#'] = 11,['$'] = 10, ['%'] = 17,['&'] = 13, ['\\'] = 4,['('] = 6, [')'] = 6,['*'] = 7, ['+'] = 10, [','] = 4, ['-'] = 6, ['.'] = 4, ['/'] = 7, ['0'] = 12, ['1'] = 7, ['2'] = 11, ['3'] = 11, ['4'] = 11, ['5'] = 11, ['6'] = 12, ['7'] = 10, ['8'] = 11, ['9'] = 11, [':'] = 5, [';'] = 4, ['<'] = 9, ['='] = 9, ['>'] = 9, ['?'] = 10, ['@'] = 15, ['A'] = 12, ['B'] = 13, ['C'] = 14, ['D'] = 14, ['E'] = 12, ['F'] = 12, ['G'] = 15, ['H'] = 14, ['I'] = 5, ['J'] = 11, ['K'] = 13, ['L'] = 11, ['M'] = 16, ['N'] = 14, ['O'] = 16, ['P'] = 12, ['Q'] = 15, ['R'] = 13, ['S'] = 12, ['T'] = 11, ['U'] = 13, ['V'] = 12, ['W'] = 18, ['X'] = 11, ['Y'] = 11, ['Z'] = 12, ['['] = 6, [']'] = 6, ['^'] = 9, ['_'] = 18, ['`'] = 8, ['a'] = 11, ['b'] = 12, ['c'] = 11, ['d'] = 12, ['e'] = 12, ['f'] = 5, ['g'] = 13, ['h'] = 11, ['i'] = 4, ['j'] = 4, ['k'] = 10, ['l'] = 4, ['m'] = 18, ['n'] = 11, ['o'] = 12, ['p'] = 12, ['q'] = 12, ['r'] = 7, ['s'] = 9, ['t'] = 5, ['u'] = 11, ['v'] = 10, ['w'] = 14, ['x'] = 9, ['y'] = 10, ['z'] = 9, ['{'] = 6, ['|'] = 3, ['}'] = 6 }
+
+BadgeStyle = { None = 0, BronzeMedal = 1, GoldMedal = 2, SilverMedal = 3, Alert = 4, Crown = 5, Ammo = 6, Armour = 7, Barber = 8, Clothes = 9, Franklin = 10, Bike = 11, Car = 12, Gun = 13, Heart = 14, Makeup = 15, Mask = 16, Michael = 17, Star = 18, Tattoo = 19, Trevor = 20, Lock = 21, Tick = 22 }
+
+BadgeTexture = {
+ [0] = function() return "" end,
+ [1] = function() return "mp_medal_bronze" end,
+ [2] = function() return "mp_medal_gold" end,
+ [3] = function() return "medal_silver" end,
+ [4] = function() return "mp_alerttriangle" end,
+ [5] = function() return "mp_hostcrown" end,
+ [6] = function(Selected) if Selected then return "shop_ammo_icon_b" else return "shop_ammo_icon_a" end end,
+ [7] = function(Selected) if Selected then return "shop_armour_icon_b" else return "shop_armour_icon_a" end end,
+ [8] = function(Selected) if Selected then return "shop_barber_icon_b" else return "shop_barber_icon_a" end end,
+ [9] = function(Selected) if Selected then return "shop_clothing_icon_b" else return "shop_clothing_icon_a" end end,
+ [10] = function(Selected) if Selected then return "shop_franklin_icon_b" else return "shop_franklin_icon_a" end end,
+ [11] = function(Selected) if Selected then return "shop_garage_bike_icon_b" else return "shop_garage_bike_icon_a" end end,
+ [12] = function(Selected) if Selected then return "shop_garage_icon_b" else return "shop_garage_icon_a" end end,
+ [13] = function(Selected) if Selected then return "shop_gunclub_icon_b" else return "shop_gunclub_icon_a" end end,
+ [14] = function(Selected) if Selected then return "shop_health_icon_b" else return "shop_health_icon_a" end end,
+ [15] = function(Selected) if Selected then return "shop_makeup_icon_b" else return "shop_makeup_icon_a" end end,
+ [16] = function(Selected) if Selected then return "shop_mask_icon_b" else return "shop_mask_icon_a" end end,
+ [17] = function(Selected) if Selected then return "shop_michael_icon_b" else return "shop_michael_icon_a" end end,
+ [18] = function() return "shop_new_star" end,
+ [19] = function(Selected) if Selected then return "shop_tattoos_icon_b" else return "shop_tattoos_icon_a" end end,
+ [20] = function(Selected) if Selected then return "shop_trevor_icon_b" else return "shop_trevor_icon_a" end end,
+ [21] = function() return "shop_lock" end,
+ [22] = function() return "shop_tick_icon" end,
+}
+
+BadgeDictionary = {
+ [0] = function(Selected)
+ if Selected then
+ return "commonmenu"
+ else
+ return "commonmenu"
+ end
+ end,
+}
+
+BadgeColour = {
+ [5] = function(Selected) if Selected then return 0, 0, 0, 255 else return 255, 255, 255, 255 end end,
+ [21] = function(Selected) if Selected then return 0, 0, 0, 255 else return 255, 255, 255, 255 end end,
+ [22] = function(Selected) if Selected then return 0, 0, 0, 255 else return 255, 255, 255, 255 end end,
+}
+
+Colours = {
+ PureWhite = {255, 255, 255, 255},
+ White = {240, 240, 240, 255},
+ Black = {0, 0, 0, 255},
+ Grey = {155, 155, 155, 255},
+ GreyLight = {205, 205, 205, 255},
+ GreyDark = {77, 77, 77, 255},
+ Red = {224, 50, 50, 255},
+ RedLight = {240, 153, 153, 255},
+ RedDark = {112, 25, 25, 255},
+ Blue = {93, 182, 229, 255},
+ BlueLight = {174, 219, 242, 255},
+ BlueDark = {47, 92, 115, 255},
+ Yellow = {240, 200, 80, 255},
+ YellowLight = {254, 235, 169, 255},
+ YellowDark = {126, 107, 41, 255},
+ Orange = {255, 133, 85, 255},
+ OrangeLight = {255, 194, 170, 255},
+ OrangeDark = {127, 66, 42, 255},
+ Green = {114, 204, 114, 255},
+ GreenLight = {185, 230, 185, 255},
+ GreenDark = {57, 102, 57, 255},
+ Purple = {132, 102, 226, 255},
+ PurpleLight = {192, 179, 239, 255},
+ PurpleDark = {67, 57, 111, 255},
+ Pink = {203, 54, 148, 255},
+ RadarHealth = {53, 154, 71, 255},
+ RadarArmour = {93, 182, 229, 255},
+ RadarDamage = {235, 36, 39, 255},
+ NetPlayer1 = {194, 80, 80, 255},
+ NetPlayer2 = {156, 110, 175, 255},
+ NetPlayer3 = {255, 123, 196, 255},
+ NetPlayer4 = {247, 159, 123, 255},
+ NetPlayer5 = {178, 144, 132, 255},
+ NetPlayer6 = {141, 206, 167, 255},
+ NetPlayer7 = {113, 169, 175, 255},
+ NetPlayer8 = {211, 209, 231, 255},
+ NetPlayer9 = {144, 127, 153, 255},
+ NetPlayer10 = {106, 196, 191, 255},
+ NetPlayer11 = {214, 196, 153, 255},
+ NetPlayer12 = {234, 142, 80, 255},
+ NetPlayer13 = {152, 203, 234, 255},
+ NetPlayer14 = {178, 98, 135, 255},
+ NetPlayer15 = {144, 142, 122, 255},
+ NetPlayer16 = {166, 117, 94, 255},
+ NetPlayer17 = {175, 168, 168, 255},
+ NetPlayer18 = {232, 142, 155, 255},
+ NetPlayer19 = {187, 214, 91, 255},
+ NetPlayer20 = {12, 123, 86, 255},
+ NetPlayer21 = {123, 196, 255, 255},
+ NetPlayer22 = {171, 60, 230, 255},
+ NetPlayer23 = {206, 169, 13, 255},
+ NetPlayer24 = {71, 99, 173, 255},
+ NetPlayer25 = {42, 166, 185, 255},
+ NetPlayer26 = {186, 157, 125, 255},
+ NetPlayer27 = {201, 225, 255, 255},
+ NetPlayer28 = {240, 240, 150, 255},
+ NetPlayer29 = {237, 140, 161, 255},
+ NetPlayer30 = {249, 138, 138, 255},
+ NetPlayer31 = {252, 239, 166, 255},
+ NetPlayer32 = {240, 240, 240, 255},
+ SimpleBlipDefault = {159, 201, 166, 255},
+ MenuBlue = {140, 140, 140, 255},
+ MenuGreyLight = {140, 140, 140, 255},
+ MenuBlueExtraDark = {40, 40, 40, 255},
+ MenuYellow = {240, 160, 0, 255},
+ MenuYellowDark = {240, 160, 0, 255},
+ MenuGreen = {240, 160, 0, 255},
+ MenuGrey = {140, 140, 140, 255},
+ MenuGreyDark = {60, 60, 60, 255},
+ MenuHighlight = {30, 30, 30, 255},
+ MenuStandard = {140, 140, 140, 255},
+ MenuDimmed = {75, 75, 75, 255},
+ MenuExtraDimmed = {50, 50, 50, 255},
+ BriefTitle = {95, 95, 95, 255},
+ MidGreyMp = {100, 100, 100, 255},
+ NetPlayer1Dark = {93, 39, 39, 255},
+ NetPlayer2Dark = {77, 55, 89, 255},
+ NetPlayer3Dark = {124, 62, 99, 255},
+ NetPlayer4Dark = {120, 80, 80, 255},
+ NetPlayer5Dark = {87, 72, 66, 255},
+ NetPlayer6Dark = {74, 103, 83, 255},
+ NetPlayer7Dark = {60, 85, 88, 255},
+ NetPlayer8Dark = {105, 105, 64, 255},
+ NetPlayer9Dark = {72, 63, 76, 255},
+ NetPlayer10Dark = {53, 98, 95, 255},
+ NetPlayer11Dark = {107, 98, 76, 255},
+ NetPlayer12Dark = {117, 71, 40, 255},
+ NetPlayer13Dark = {76, 101, 117, 255},
+ NetPlayer14Dark = {65, 35, 47, 255},
+ NetPlayer15Dark = {72, 71, 61, 255},
+ NetPlayer16Dark = {85, 58, 47, 255},
+ NetPlayer17Dark = {87, 84, 84, 255},
+ NetPlayer18Dark = {116, 71, 77, 255},
+ NetPlayer19Dark = {93, 107, 45, 255},
+ NetPlayer20Dark = {6, 61, 43, 255},
+ NetPlayer21Dark = {61, 98, 127, 255},
+ NetPlayer22Dark = {85, 30, 115, 255},
+ NetPlayer23Dark = {103, 84, 6, 255},
+ NetPlayer24Dark = {35, 49, 86, 255},
+ NetPlayer25Dark = {21, 83, 92, 255},
+ NetPlayer26Dark = {93, 98, 62, 255},
+ NetPlayer27Dark = {100, 112, 127, 255},
+ NetPlayer28Dark = {120, 120, 75, 255},
+ NetPlayer29Dark = {152, 76, 93, 255},
+ NetPlayer30Dark = {124, 69, 69, 255},
+ NetPlayer31Dark = {10, 43, 50, 255},
+ NetPlayer32Dark = {95, 95, 10, 255},
+ Bronze = {180, 130, 97, 255},
+ Silver = {150, 153, 161, 255},
+ Gold = {214, 181, 99, 255},
+ Platinum = {166, 221, 190, 255},
+ Gang1 = {29, 100, 153, 255},
+ Gang2 = {214, 116, 15, 255},
+ Gang3 = {135, 125, 142, 255},
+ Gang4 = {229, 119, 185, 255},
+ SameCrew = {252, 239, 166, 255},
+ Freemode = {45, 110, 185, 255},
+ PauseBg = {0, 0, 0, 255},
+ Friendly = {93, 182, 229, 255},
+ Enemy = {194, 80, 80, 255},
+ Location = {240, 200, 80, 255},
+ Pickup = {114, 204, 114, 255},
+ PauseSingleplayer = {114, 204, 114, 255},
+ FreemodeDark = {22, 55, 92, 255},
+ InactiveMission = {154, 154, 154, 255},
+ Damage = {194, 80, 80, 255},
+ PinkLight = {252, 115, 201, 255},
+ PmMitemHighlight = {252, 177, 49, 255},
+ ScriptVariable = {0, 0, 0, 255},
+ Yoga = {109, 247, 204, 255},
+ Tennis = {241, 101, 34, 255},
+ Golf = {214, 189, 97, 255},
+ ShootingRange = {112, 25, 25, 255},
+ FlightSchool = {47, 92, 115, 255},
+ NorthBlue = {93, 182, 229, 255},
+ SocialClub = {234, 153, 28, 255},
+ PlatformBlue = {11, 55, 123, 255},
+ PlatformGreen = {146, 200, 62, 255},
+ PlatformGrey = {234, 153, 28, 255},
+ FacebookBlue = {66, 89, 148, 255},
+ IngameBg = {0, 0, 0, 255},
+ Darts = {114, 204, 114, 255},
+ Waypoint = {164, 76, 242, 255},
+ Michael = {101, 180, 212, 255},
+ Franklin = {171, 237, 171, 255},
+ Trevor = {255, 163, 87, 255},
+ GolfP1 = {240, 240, 240, 255},
+ GolfP2 = {235, 239, 30, 255},
+ GolfP3 = {255, 149, 14, 255},
+ GolfP4 = {246, 60, 161, 255},
+ WaypointLight = {210, 166, 249, 255},
+ WaypointDark = {82, 38, 121, 255},
+ PanelLight = {0, 0, 0, 255},
+ MichaelDark = {72, 103, 116, 255},
+ FranklinDark = {85, 118, 85, 255},
+ TrevorDark = {127, 81, 43, 255},
+ ObjectiveRoute = {240, 200, 80, 255},
+ PausemapTint = {0, 0, 0, 255},
+ PauseDeselect = {100, 100, 100, 255},
+ PmWeaponsPurchasable = {45, 110, 185, 255},
+ PmWeaponsLocked = {240, 240, 240, 255},
+ ScreenBg = {0, 0, 0, 255},
+ Chop = {224, 50, 50, 255},
+ PausemapTintHalf = {0, 0, 0, 255},
+ NorthBlueOfficial = {0, 71, 133, 255},
+ ScriptVariable2 = {0, 0, 0, 255},
+ H = {33, 118, 37, 255},
+ HDark = {37, 102, 40, 255},
+ T = {234, 153, 28, 255},
+ TDark = {225, 140, 8, 255},
+ HShard = {20, 40, 0, 255},
+ ControllerMichael = {48, 255, 255, 255},
+ ControllerFranklin = {48, 255, 0, 255},
+ ControllerTrevor = {176, 80, 0, 255},
+ ControllerChop = {127, 0, 0, 255},
+ VideoEditorVideo = {53, 166, 224, 255},
+ VideoEditorAudio = {162, 79, 157, 255},
+ VideoEditorText = {104, 192, 141, 255},
+ HbBlue = {29, 100, 153, 255},
+ HbYellow = {234, 153, 28, 255},
+ VideoEditorScore = {240, 160, 1, 255},
+ VideoEditorAudioFadeout = {59, 34, 57, 255},
+ VideoEditorTextFadeout = {41, 68, 53, 255},
+ VideoEditorScoreFadeout = {82, 58, 10, 255},
+ HeistBackground = {37, 102, 40, 255},
+ VideoEditorAmbient = {240, 200, 80, 255},
+ VideoEditorAmbientFadeout = {80, 70, 34, 255},
+ Gb = {255, 133, 85, 255},
+ G = {255, 194, 170, 255},
+ B = {255, 133, 85, 255},
+ LowFlow = {240, 200, 80, 255},
+ LowFlowDark = {126, 107, 41, 255},
+ G1 = {247, 159, 123, 255},
+ G2 = {226, 134, 187, 255},
+ G3 = {239, 238, 151, 255},
+ G4 = {113, 169, 175, 255},
+ G5 = {160, 140, 193, 255},
+ G6 = {141, 206, 167, 255},
+ G7 = {181, 214, 234, 255},
+ G8 = {178, 144, 132, 255},
+ G9 = {0, 132, 114, 255},
+ G10 = {216, 85, 117, 255},
+ G11 = {30, 100, 152, 255},
+ G12 = {43, 181, 117, 255},
+ G13 = {233, 141, 79, 255},
+ G14 = {137, 210, 215, 255},
+ G15 = {134, 125, 141, 255},
+ Adversary = {109, 34, 33, 255},
+ DegenRed = {255, 0, 0, 255},
+ DegenYellow = {255, 255, 0, 255},
+ DegenGreen = {0, 255, 0, 255},
+ DegenCyan = {0, 255, 255, 255},
+ DegenBlue = {0, 0, 255, 255},
+ DegenMagenta = {255, 0, 255, 255},
+ Stunt1 = {38, 136, 234, 255},
+ Stunt2 = {224, 50, 50, 255},
+}
+
+--[[
+ Utils.lua
+ Utilities
+--]]
+
+function GetResolution()
+ local W, H = GetActiveScreenResolution()
+ if (W/H) > 3.5 then
+ return GetScreenResolution()
+ else
+ return W, H
+ end
+end
+
+function FormatXWYH(Value, Value2)
+ return Value/1920, Value2/1080
+end
+
+function math.round(num, numDecimalPlaces)
+ return tonumber(string.format("%." .. (numDecimalPlaces or 0) .. "f", num))
+end
+
+function tobool(input)
+ if input == "true" or tonumber(input) == 1 or input == true then
+ return true
+ else
+ return false
+ end
+end
+
+function string.split(inputstr, sep)
+ if sep == nil then
+ sep = "%s"
+ end
+ local t={} ; i=1
+ for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
+ t[i] = str
+ i = i + 1
+ end
+
+ return t
+end
+
+function string.starts(String, Start)
+ return string.sub(String, 1, string.len(Start)) == Start
+end
+
+function IsMouseInBounds(X, Y, Width, Height)
+ local MX, MY = math.round(GetControlNormal(0, 239) * 1920), math.round(GetControlNormal(0, 240) * 1080)
+ MX, MY = FormatXWYH(MX, MY)
+ X, Y = FormatXWYH(X, Y)
+ Width, Height = FormatXWYH(Width, Height)
+ return (MX >= X and MX <= X + Width) and (MY > Y and MY < Y + Height)
+end
+
+function GetSafeZoneBounds()
+ local SafeSize = GetSafeZoneSize()
+ SafeSize = math.round(SafeSize, 2)
+ SafeSize = (SafeSize * 100) - 90
+ SafeSize = 10 - SafeSize
+
+ local W, H = 1920, 1080
+
+ return {X = math.round(SafeSize * ((W/H) * 5.4)), Y = math.round(SafeSize * 5.4)}
+end
+
+function Controller()
+ return not IsInputDisabled(2)
+end
+
+--[[
+ UIResRectangle.lua
+ Elements
+--]]
+
+function UIResRectangle.New(X, Y, Width, Height, R, G, B, A)
+ local _UIResRectangle = {
+ X = tonumber(X) or 0,
+ Y = tonumber(Y) or 0,
+ Width = tonumber(Width) or 0,
+ Height = tonumber(Height) or 0,
+ _Colour = {R = tonumber(R) or 255, G = tonumber(G) or 255, B = tonumber(B) or 255, A = tonumber(A) or 255},
+ }
+ return setmetatable(_UIResRectangle, UIResRectangle)
+end
+
+function UIResRectangle:Position(X, Y)
+ if tonumber(X) and tonumber(Y) then
+ self.X = tonumber(X)
+ self.Y = tonumber(Y)
+ else
+ return {X = self.X, Y = self.Y}
+ end
+end
+
+function UIResRectangle:Size(Width, Height)
+ if tonumber(Width) and tonumber(Height) then
+ self.Width = tonumber(Width)
+ self.Height = tonumber(Height)
+ else
+ return {Width = self.Width, Height = self.Height}
+ end
+end
+
+function UIResRectangle:Colour(R, G, B, A)
+ if tonumber(R) or tonumber(G) or tonumber(B) or tonumber(A) then
+ self._Colour.R = tonumber(R) or 255
+ self._Colour.B = tonumber(B) or 255
+ self._Colour.G = tonumber(G) or 255
+ self._Colour.A = tonumber(A) or 255
+ else
+ return self._Colour
+ end
+end
+
+function UIResRectangle:Draw()
+ local Position = self:Position()
+ local Size = self:Size()
+ Size.Width, Size.Height = FormatXWYH(Size.Width, Size.Height)
+ Position.X, Position.Y = FormatXWYH(Position.X, Position.Y)
+ DrawRect(Position.X + Size.Width * 0.5, Position.Y + Size.Height * 0.5, Size.Width, Size.Height, self._Colour.R, self._Colour.G, self._Colour.B, self._Colour.A)
+end
+
+function DrawRectangle(X, Y, Width, Height, R, G, B, A)
+ X, Y, Width, Height = X or 0, Y or 0, Width or 0, Height or 0
+ X, Y = FormatXWYH(X, Y)
+ Width, Height = FormatXWYH(Width, Height)
+ DrawRect(X + Width * 0.5, Y + Height * 0.5, Width, Height, tonumber(R) or 255, tonumber(G) or 255, tonumber(B) or 255, tonumber(A) or 255)
+end
+
+--[[
+ UIResText.lua
+ Elements
+--]]
+
+function GetCharacterCount(str)
+ local characters = 0
+ for c in str:gmatch("[%z\1-\127\194-\244][\128-\191]*") do
+ local a = c:byte(1, -1)
+ if a ~= nil then
+ characters = characters + 1
+ end
+ end
+ return characters
+end
+
+function GetByteCount(str)
+ local bytes = 0
+
+ for c in str:gmatch("[%z\1-\127\194-\244][\128-\191]*") do
+ local a,b,c,d = c:byte(1, -1)
+ if a ~= nil then
+ bytes = bytes + 1
+ end
+ if b ~= nil then
+ bytes = bytes + 1
+ end
+ if c ~= nil then
+ bytes = bytes + 1
+ end
+ if d ~= nil then
+ bytes = bytes + 1
+ end
+ end
+ return bytes
+end
+
+function AddLongStringForAscii(str)
+ local maxbytelength = 99
+ for i = 0, GetCharacterCount(str), 99 do
+ AddTextComponentSubstringPlayerName(string.sub(str, i, math.min(maxbytelength, GetCharacterCount(str) - i))) --needs changed
+ end
+end
+
+function AddLongStringForUtf8(str)
+ local maxbytelength = 99
+ local bytecount = GetByteCount(str)
+
+ if bytecount < maxbytelength then
+ AddTextComponentSubstringPlayerName(str)
+ return
+ end
+
+ local startIndex = 0
+
+ for i = 0, GetCharacterCount(str), 1 do
+ local length = i - startIndex
+ if GetByteCount(string.sub(str, startIndex, length)) > maxbytelength then
+ AddTextComponentSubstringPlayerName(string.sub(str, startIndex, length - 1))
+ i = i - 1
+ startIndex = startIndex + (length - 1)
+ end
+ end
+ AddTextComponentSubstringPlayerName(string.sub(str, startIndex, GetCharacterCount(str) - startIndex))
+end
+
+function AddLongString(str)
+ local bytecount = GetByteCount(str)
+ if bytecount == GetCharacterCount(str) then
+ AddLongStringForAscii(str)
+ else
+ AddLongStringForUtf8(str)
+ end
+end
+
+function MeasureStringWidthNoConvert(str, font, scale)
+ BeginTextCommandWidth("STRING")
+ AddLongString(str)
+ SetTextFont(font or 0)
+ SetTextScale(1.0, scale or 0)
+ return EndTextCommandGetWidth(true)
+end
+
+function MeasureStringWidth(str, font, scale)
+ return MeasureStringWidthNoConvert(str, font, scale) * 1920
+end
+
+function UIResText.New(Text, X, Y, Scale, R, G, B, A, Font, Alignment, DropShadow, Outline, WordWrap)
+ local _UIResText = {
+ _Text = tostring(Text) or "",
+ X = tonumber(X) or 0,
+ Y = tonumber(Y) or 0,
+ Scale = tonumber(Scale) or 0,
+ _Colour = {R = tonumber(R) or 255, G = tonumber(G) or 255, B = tonumber(B) or 255, A = tonumber(A) or 255},
+ Font = tonumber(Font) or 0,
+ Alignment = Alignment or nil,
+ DropShadow = Dropshadow or nil,
+ Outline = Outline or nil,
+ WordWrap = tonumber(WordWrap) or 0,
+ }
+ return setmetatable(_UIResText, UIResText)
+end
+
+function UIResText:Position(X, Y)
+ if tonumber(X) and tonumber(Y) then
+ self.X = tonumber(X)
+ self.Y = tonumber(Y)
+ else
+ return {X = self.X, Y = self.Y}
+ end
+end
+
+function UIResText:Colour(R, G, B, A)
+ if tonumber(R) and tonumber(G) and tonumber(B) and tonumber(A) then
+ self._Colour.R = tonumber(R)
+ self._Colour.B = tonumber(B)
+ self._Colour.G = tonumber(G)
+ self._Colour.A = tonumber(A)
+ else
+ return self._Colour
+ end
+end
+
+function UIResText:Text(Text)
+ if tostring(Text) and Text ~= nil then
+ self._Text = tostring(Text)
+ else
+ return self._Text
+ end
+end
+
+function UIResText:Draw()
+ local Position = self:Position()
+ Position.X, Position.Y = FormatXWYH(Position.X, Position.Y)
+
+ SetTextFont(self.Font)
+ SetTextScale(1.0, self.Scale)
+ SetTextColour(self._Colour.R, self._Colour.G, self._Colour.B, self._Colour.A)
+
+ if self.DropShadow then
+ SetTextDropShadow()
+ end
+ if self.Outline then
+ SetTextOutline()
+ end
+
+ if self.Alignment ~= nil then
+ if self.Alignment == 1 or self.Alignment == "Center" or self.Alignment == "Centre" then
+ SetTextCentre(true)
+ elseif self.Alignment == 2 or self.Alignment == "Right" then
+ SetTextRightJustify(true)
+ SetTextWrap(0, Position.X)
+ end
+ end
+
+ if tonumber(self.WordWrap) then
+ if tonumber(self.WordWrap) ~= 0 then
+ SetTextWrap(Position.X, Position.X + (tonumber(self.WordWrap) / Resolution.Width))
+ end
+ end
+
+ BeginTextCommandDisplayText("STRING")
+ AddLongString(self._Text)
+ EndTextCommandDisplayText(Position.X, Position.Y)
+end
+
+function RenderText(Text, X, Y, Font, Scale, R, G, B, A, Alignment, DropShadow, Outline, WordWrap)
+ Text = tostring(Text)
+ X, Y = FormatXWYH(X, Y)
+ SetTextFont(Font or 0)
+ SetTextScale(1.0, Scale or 0)
+ SetTextColour(R or 255, G or 255, B or 255, A or 255)
+
+ if DropShadow then
+ SetTextDropShadow()
+ end
+ if Outline then
+ SetTextOutline()
+ end
+
+ if Alignment ~= nil then
+ if Alignment == 1 or Alignment == "Center" or Alignment == "Centre" then
+ SetTextCentre(true)
+ elseif Alignment == 2 or Alignment == "Right" then
+ SetTextRightJustify(true)
+ SetTextWrap(0, X)
+ end
+ end
+
+ if tonumber(WordWrap) then
+ if tonumber(WordWrap) ~= 0 then
+ WordWrap, _ = FormatXWYH(WordWrap, 0)
+ SetTextWrap(WordWrap, X - WordWrap)
+ end
+ end
+
+ BeginTextCommandDisplayText("STRING")
+ AddLongString(Text)
+ EndTextCommandDisplayText(X, Y)
+end
+
+--[[
+ Sprite.lua
+ Elements
+--]]
+
+function Sprite.New(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A)
+ local _Sprite = {
+ TxtDictionary = tostring(TxtDictionary),
+ TxtName = tostring(TxtName),
+ X = tonumber(X) or 0,
+ Y = tonumber(Y) or 0,
+ Width = tonumber(Width) or 0,
+ Height = tonumber(Height) or 0,
+ Heading = tonumber(Heading) or 0,
+ _Colour = {R = tonumber(R) or 255, G = tonumber(G) or 255, B = tonumber(B) or 255, A = tonumber(A) or 255},
+ }
+ return setmetatable(_Sprite, Sprite)
+end
+
+function Sprite:Position(X, Y)
+ if tonumber(X) and tonumber(Y) then
+ self.X = tonumber(X)
+ self.Y = tonumber(Y)
+ else
+ return {X = self.X, Y = self.Y}
+ end
+end
+
+function Sprite:Size(Width, Height)
+ if tonumber(Width) and tonumber(Width) then
+ self.Width = tonumber(Width)
+ self.Height = tonumber(Height)
+ else
+ return {Width = self.Width, Height = self.Height}
+ end
+end
+
+function Sprite:Colour(R, G, B, A)
+ if tonumber(R) or tonumber(G) or tonumber(B) or tonumber(A) then
+ self._Colour.R = tonumber(R) or 255
+ self._Colour.B = tonumber(B) or 255
+ self._Colour.G = tonumber(G) or 255
+ self._Colour.A = tonumber(A) or 255
+ else
+ return self._Colour
+ end
+end
+
+function Sprite:Draw()
+ if not HasStreamedTextureDictLoaded(self.TxtDictionary) then
+ RequestStreamedTextureDict(self.TxtDictionary, true)
+ end
+ local Position = self:Position()
+ local Size = self:Size()
+ Size.Width, Size.Height = FormatXWYH(Size.Width, Size.Height)
+ Position.X, Position.Y = FormatXWYH(Position.X, Position.Y)
+ DrawSprite(self.TxtDictionary, self.TxtName, Position.X + Size.Width * 0.5, Position.Y + Size.Height * 0.5, Size.Width, Size.Height, self.Heading, self._Colour.R, self._Colour.G, self._Colour.B, self._Colour.A)
+end
+
+function DrawTexture(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A)
+ if not HasStreamedTextureDictLoaded(tostring(TxtDictionary) or "") then
+ RequestStreamedTextureDict(tostring(TxtDictionary) or "", true)
+ end
+ X, Y, Width, Height = X or 0, Y or 0, Width or 0, Height or 0
+ X, Y = FormatXWYH(X, Y)
+ Width, Height = FormatXWYH(Width, Height)
+ DrawSprite(tostring(TxtDictionary) or "", tostring(TxtName) or "", X + Width * 0.5, Y + Height * 0.5, Width, Height, tonumber(Heading) or 0, tonumber(R) or 255, tonumber(G) or 255, tonumber(B) or 255, tonumber(A) or 255)
+end
+
+--[[
+ StringMeasurer.lua
+ Elements
+--]]
+
+function MeasureString(str)
+ local output = 0
+ for i = 1, GetCharacterCount(str), 1 do
+ if CharacterMap[string.sub(str, i, i)] then
+ output = output + CharacterMap[string.sub(str, i, i)] + 1
+ end
+ end
+ return output
+end
+
+--[[
+ Badge.lua
+ Elements
+--]]
+
+function GetBadgeTexture(Badge, Selected)
+ if BadgeTexture[Badge] then
+ return BadgeTexture[Badge](Selected)
+ else
+ return ""
+ end
+end
+
+function GetBadgeDictionary(Badge, Selected)
+ if BadgeDictionary[Badge] then
+ return BadgeDictionary[Badge](Selected)
+ else
+ return "commonmenu"
+ end
+end
+
+function GetBadgeColour(Badge, Selected)
+ if BadgeColour[Badge] then
+ return BadgeColour[Badge](Selected)
+ else
+ return 255, 255, 255, 255
+ end
+end
+
+--[[
+ Colours.lua
+ Elements
+--]]
+
+--[[
+ UIMenuItem.lua
+ Items
+--]]
+
+function UIMenuItem.New(Text, Description)
+ _UIMenuItem = {
+ Rectangle = UIResRectangle.New(0, 0, 431, 38, 255, 255, 255, 20),
+ Text = UIResText.New(tostring(Text) or "", 8, 0, 0.33, 245, 245, 245, 255, 0),
+ _Description = tostring(Description) or "";
+ SelectedSprite = Sprite.New("commonmenu", "gradient_nav", 0, 0, 431, 38),
+ LeftBadge = { Sprite = Sprite.New("commonmenu", "", 0, 0, 40, 40), Badge = 0},
+ RightBadge = { Sprite = Sprite.New("commonmenu", "", 0, 0, 40, 40), Badge = 0},
+ Label = {
+ Text = UIResText.New("", 0, 0, 0.35, 245, 245, 245, 255, 0, "Right"),
+ MainColour = {R = 255, G = 255, B = 255, A = 255},
+ HighlightColour = {R = 0, G = 0, B = 0, A = 255},
+ },
+ _Selected = false,
+ _Hovered = false,
+ _Enabled = true,
+ _Offset = {X = 0, Y = 0},
+ ParentMenu = nil,
+ Panels = {},
+ Activated = function(menu, item, panels) end,
+ ActivatedPanel = function(menu, item, panel, panelvalue) end,
+ }
+ return setmetatable(_UIMenuItem, UIMenuItem)
+end
+
+function UIMenuItem:SetParentMenu(Menu)
+ if Menu ~= nil and Menu() == "UIMenu" then
+ self.ParentMenu = Menu
+ else
+ return self.ParentMenu
+ end
+end
+
+function UIMenuItem:Selected(bool)
+ if bool ~= nil then
+ self._Selected = tobool(bool)
+ else
+ return self._Selected
+ end
+end
+
+function UIMenuItem:Hovered(bool)
+ if bool ~= nil then
+ self._Hovered = tobool(bool)
+ else
+ return self._Hovered
+ end
+end
+
+function UIMenuItem:Enabled(bool)
+ if bool ~= nil then
+ self._Enabled = tobool(bool)
+ else
+ return self._Enabled
+ end
+end
+
+function UIMenuItem:Description(str)
+ if tostring(str) and str ~= nil then
+ self._Description = tostring(str)
+ else
+ return self._Description
+ end
+end
+
+function UIMenuItem:Offset(X, Y)
+ if tonumber(X) or tonumber(Y) then
+ if tonumber(X) then
+ self._Offset.X = tonumber(X)
+ end
+ if tonumber(Y) then
+ self._Offset.Y = tonumber(Y)
+ end
+ else
+ return self._Offset
+ end
+end
+
+function UIMenuItem:Position(Y)
+ if tonumber(Y) then
+ self.Rectangle:Position(self._Offset.X, Y + 144 + self._Offset.Y)
+ self.SelectedSprite:Position(0 + self._Offset.X, Y + 144 + self._Offset.Y)
+ self.Text:Position(8 + self._Offset.X, Y + 147 + self._Offset.Y)
+ self.LeftBadge.Sprite:Position(0 + self._Offset.X, Y + 142 + self._Offset.Y)
+ self.RightBadge.Sprite:Position(385 + self._Offset.X, Y + 142 + self._Offset.Y)
+ self.Label.Text:Position(420 + self._Offset.X, Y + 148 + self._Offset.Y)
+ end
+end
+
+function UIMenuItem:RightLabel(Text, MainColour, HighlightColour)
+ if tostring(Text) and Text ~= nil then
+ if type(MainColour) == "table" then
+ self.Label.MainColour = MainColour
+ end
+ if type(HighlightColour) == "table" then
+ self.Label.HighlightColour = HighlightColour
+ end
+ self.Label.Text:Text(tostring(Text))
+ else
+ return self.Label.Text:Text()
+ end
+end
+
+function UIMenuItem:SetLeftBadge(Badge)
+ if tonumber(Badge) then
+ self.LeftBadge.Badge = tonumber(Badge)
+ end
+end
+
+function UIMenuItem:SetRightBadge(Badge)
+ if tonumber(Badge) then
+ self.RightBadge.Badge = tonumber(Badge)
+ end
+end
+
+function UIMenuItem:Text(Text)
+ if tostring(Text) and Text ~= nil then
+ self.Text:Text(tostring(Text))
+ else
+ return self.Text:Text()
+ end
+end
+
+function UIMenuItem:AddPanel(Panel)
+ if Panel() == "UIMenuPanel" then
+ table.insert(self.Panels, Panel)
+ Panel:SetParentItem(self)
+ end
+end
+
+function UIMenuItem:RemovePanelAt(Index)
+ if tonumber(Index) then
+ if self.Panels[Index] then
+ table.remove(self.Panels, tonumber(Index))
+ end
+ end
+end
+
+function UIMenuItem:FindPanelIndex(Panel)
+ if Panel() == "UIMenuPanel" then
+ for Index = 1, #self.Panels do
+ if self.Panels[Index] == Panel then
+ return Index
+ end
+ end
+ end
+ return nil
+end
+
+function UIMenuItem:FindPanelItem()
+ for Index = #self.Items, 1, -1 do
+ if self.Items[Index].Panel then
+ return Index
+ end
+ end
+ return nil
+end
+
+function UIMenuItem:Draw()
+ self.Rectangle:Size(431 + self.ParentMenu.WidthOffset, self.Rectangle.Height)
+ self.SelectedSprite:Size(431 + self.ParentMenu.WidthOffset, self.SelectedSprite.Height)
+
+ if self._Hovered and not self._Selected then
+ self.Rectangle:Draw()
+ end
+
+ if self._Selected then
+ self.SelectedSprite:Draw()
+ end
+
+ if self._Enabled then
+ if self._Selected then
+ self.Text:Colour(0, 0, 0, 255)
+ self.Label.Text:Colour(self.Label.HighlightColour.R, self.Label.HighlightColour.G, self.Label.HighlightColour.B, self.Label.HighlightColour.A)
+ else
+ self.Text:Colour(245, 245, 245, 255)
+ self.Label.Text:Colour(self.Label.MainColour.R, self.Label.MainColour.G, self.Label.MainColour.B, self.Label.MainColour.A)
+ end
+ else
+ self.Text:Colour(163, 159, 148, 255)
+ self.Label.Text:Colour(163, 159, 148, 255)
+ end
+
+ if self.LeftBadge.Badge == BadgeStyle.None then
+ self.Text:Position(8 + self._Offset.X, self.Text.Y)
+ else
+ self.Text:Position(35 + self._Offset.X, self.Text.Y)
+ self.LeftBadge.Sprite.TxtDictionary = GetBadgeDictionary(self.LeftBadge.Badge, self._Selected)
+ self.LeftBadge.Sprite.TxtName = GetBadgeTexture(self.LeftBadge.Badge, self._Selected)
+ self.LeftBadge.Sprite:Colour(GetBadgeColour(self.LeftBadge.Badge, self._Selected))
+ self.LeftBadge.Sprite:Draw()
+ end
+
+ if self.RightBadge.Badge ~= BadgeStyle.None then
+ self.RightBadge.Sprite:Position(385 + self._Offset.X + self.ParentMenu.WidthOffset, self.RightBadge.Sprite.Y)
+ self.RightBadge.Sprite.TxtDictionary = GetBadgeDictionary(self.RightBadge.Badge, self._Selected)
+ self.RightBadge.Sprite.TxtName = GetBadgeTexture(self.RightBadge.Badge, self._Selected)
+ self.RightBadge.Sprite:Colour(GetBadgeColour(self.RightBadge.Badge, self._Selected))
+ self.RightBadge.Sprite:Draw()
+ end
+
+ if self.Label.Text:Text() ~= "" and string.len(self.Label.Text:Text()) > 0 then
+ self.Label.Text:Position(420 + self._Offset.X + self.ParentMenu.WidthOffset, self.Label.Text.Y)
+ self.Label.Text:Draw()
+ end
+
+ self.Text:Draw()
+end
+
+--[[
+ UIMenuCheckboxItem.lua
+ Items
+--]]
+
+function UIMenuCheckboxItem.New(Text, Check, Description)
+ local _UIMenuCheckboxItem = {
+ Base = UIMenuItem.New(Text or "", Description or ""),
+ CheckedSprite = Sprite.New("commonmenu", "shop_box_blank", 410, 95, 50, 50),
+ Checked = tobool(Check),
+ CheckboxEvent = function(menu, item, checked) end,
+ }
+ return setmetatable(_UIMenuCheckboxItem, UIMenuCheckboxItem)
+end
+
+function UIMenuCheckboxItem:SetParentMenu(Menu)
+ if Menu() == "UIMenu" then
+ self.Base.ParentMenu = Menu
+ else
+ return self.Base.ParentMenu
+ end
+end
+
+function UIMenuCheckboxItem:Position(Y)
+ if tonumber(Y) then
+ self.Base:Position(Y)
+ self.CheckedSprite:Position(380 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 138 + self.Base._Offset.Y)
+ end
+end
+
+function UIMenuCheckboxItem:Selected(bool)
+ if bool ~= nil then
+ self.Base._Selected = tobool(bool)
+ else
+ return self.Base._Selected
+ end
+end
+
+function UIMenuCheckboxItem:Hovered(bool)
+ if bool ~= nil then
+ self.Base._Hovered = tobool(bool)
+ else
+ return self.Base._Hovered
+ end
+end
+
+function UIMenuCheckboxItem:Enabled(bool)
+ if bool ~= nil then
+ self.Base._Enabled = tobool(bool)
+ else
+ return self.Base._Enabled
+ end
+end
+
+function UIMenuCheckboxItem:Description(str)
+ if tostring(str) and str ~= nil then
+ self.Base._Description = tostring(str)
+ else
+ return self.Base._Description
+ end
+end
+
+function UIMenuCheckboxItem:Offset(X, Y)
+ if tonumber(X) or tonumber(Y) then
+ if tonumber(X) then
+ self.Base._Offset.X = tonumber(X)
+ end
+ if tonumber(Y) then
+ self.Base._Offset.Y = tonumber(Y)
+ end
+ else
+ return self.Base._Offset
+ end
+end
+
+function UIMenuCheckboxItem:Text(Text)
+ if tostring(Text) and Text ~= nil then
+ self.Base.Text:Text(tostring(Text))
+ else
+ return self.Base.Text:Text()
+ end
+end
+
+function UIMenuCheckboxItem:SetLeftBadge()
+ error("This item does not support badges")
+end
+
+function UIMenuCheckboxItem:SetRightBadge()
+ error("This item does not support badges")
+end
+
+function UIMenuCheckboxItem:RightLabel()
+ error("This item does not support a right label")
+end
+
+function UIMenuCheckboxItem:Draw()
+ self.Base:Draw()
+ self.CheckedSprite:Position(380 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.CheckedSprite.Y)
+ if self.Base:Selected() then
+ if self.Checked then
+ self.CheckedSprite.TxtName = "shop_box_tickb"
+ else
+ self.CheckedSprite.TxtName = "shop_box_blankb"
+ end
+ else
+ if self.Checked then
+ self.CheckedSprite.TxtName = "shop_box_tick"
+ else
+ self.CheckedSprite.TxtName = "shop_box_blank"
+ end
+ end
+ self.CheckedSprite:Draw()
+end
+
+--[[
+ UIMenuListItem.lua
+ Items
+--]]
+
+function UIMenuListItem.New(Text, Items, Index, Description)
+ if type(Items) ~= "table" then Items = {} end
+ if Index == 0 then Index = 1 end
+ local _UIMenuListItem = {
+ Base = UIMenuItem.New(Text or "", Description or ""),
+ Items = Items,
+ LeftArrow = Sprite.New("commonmenu", "arrowleft", 110, 105, 30, 30),
+ RightArrow = Sprite.New("commonmenu", "arrowright", 280, 105, 30, 30),
+ ItemText = UIResText.New("", 290, 104, 0.35, 255, 255, 255, 255, 0, "Right"),
+ _Index = tonumber(Index) or 1,
+ Panels = {},
+ OnListChanged = function(menu, item, newindex) end,
+ OnListSelected = function(menu, item, newindex) end,
+ }
+ return setmetatable(_UIMenuListItem, UIMenuListItem)
+end
+
+function UIMenuListItem:SetParentMenu(Menu)
+ if Menu ~= nil and Menu() == "UIMenu" then
+ self.Base.ParentMenu = Menu
+ else
+ return self.Base.ParentMenu
+ end
+end
+
+function UIMenuListItem:Position(Y)
+ if tonumber(Y) then
+ self.LeftArrow:Position(300 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 147 + Y + self.Base._Offset.Y)
+ self.RightArrow:Position(400 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 147 + Y + self.Base._Offset.Y)
+ self.ItemText:Position(300 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 147 + Y + self.Base._Offset.Y)
+ self.Base:Position(Y)
+ end
+end
+
+function UIMenuListItem:Selected(bool)
+ if bool ~= nil then
+ self.Base._Selected = tobool(bool)
+ else
+ return self.Base._Selected
+ end
+end
+
+function UIMenuListItem:Hovered(bool)
+ if bool ~= nil then
+ self.Base._Hovered = tobool(bool)
+ else
+ return self.Base._Hovered
+ end
+end
+
+function UIMenuListItem:Enabled(bool)
+ if bool ~= nil then
+ self.Base._Enabled = tobool(bool)
+ else
+ return self.Base._Enabled
+ end
+end
+
+function UIMenuListItem:Description(str)
+ if tostring(str) and str ~= nil then
+ self.Base._Description = tostring(str)
+ else
+ return self.Base._Description
+ end
+end
+
+function UIMenuListItem:Offset(X, Y)
+ if tonumber(X) or tonumber(Y) then
+ if tonumber(X) then
+ self.Base._Offset.X = tonumber(X)
+ end
+ if tonumber(Y) then
+ self.Base._Offset.Y = tonumber(Y)
+ end
+ else
+ return self.Base._Offset
+ end
+end
+
+function UIMenuListItem:Text(Text)
+ if tostring(Text) and Text ~= nil then
+ self.Base.Text:Text(tostring(Text))
+ else
+ return self.Base.Text:Text()
+ end
+end
+
+function UIMenuListItem:Index(Index)
+ if tonumber(Index) then
+ if tonumber(Index) > #self.Items then
+ self._Index = 1
+ elseif tonumber(Index) < 1 then
+ self._Index = #self.Items
+ else
+ self._Index = tonumber(Index)
+ end
+ else
+ return self._Index
+ end
+end
+
+function UIMenuListItem:ItemToIndex(Item)
+ for i = 1, #self.Items do
+ if type(Item) == type(self.Items[i]) and Item == self.Items[i] then
+ return i
+ elseif type(self.Items[i]) == "table" and (type(Item) == type(self.Items[i].Name) or type(Item) == type(self.Items[i].Value)) and (Item == self.Items[i].Name or Item == self.Items[i].Value) then
+ return i
+ end
+ end
+end
+
+function UIMenuListItem:IndexToItem(Index)
+ if tonumber(Index) then
+ if tonumber(Index) == 0 then Index = 1 end
+ if self.Items[tonumber(Index)] then
+ return self.Items[tonumber(Index)]
+ end
+ end
+end
+
+function UIMenuListItem:SetLeftBadge()
+ error("This item does not support badges")
+end
+
+function UIMenuListItem:SetRightBadge()
+ error("This item does not support badges")
+end
+
+function UIMenuListItem:RightLabel()
+ error("This item does not support a right label")
+end
+
+function UIMenuListItem:AddPanel(Panel)
+ if Panel() == "UIMenuPanel" then
+ table.insert(self.Panels, Panel)
+ Panel:SetParentItem(self)
+ end
+end
+
+function UIMenuListItem:RemovePanelAt(Index)
+ if tonumber(Index) then
+ if self.Panels[Index] then
+ table.remove(self.Panels, tonumber(Index))
+ end
+ end
+end
+
+function UIMenuListItem:FindPanelIndex(Panel)
+ if Panel() == "UIMenuPanel" then
+ for Index = 1, #self.Panels do
+ if self.Panels[Index] == Panel then
+ return Index
+ end
+ end
+ end
+ return nil
+end
+
+function UIMenuListItem:FindPanelItem()
+ for Index = #self.Items, 1, -1 do
+ if self.Items[Index].Panel then
+ return Index
+ end
+ end
+ return nil
+end
+
+function UIMenuListItem:Draw()
+ self.Base:Draw()
+
+ if self:Enabled() then
+ if self:Selected() then
+ self.ItemText:Colour(0, 0, 0, 255)
+ self.LeftArrow:Colour(0, 0, 0, 255)
+ self.RightArrow:Colour(0, 0, 0, 255)
+ else
+ self.ItemText:Colour(245, 245, 245, 255)
+ self.LeftArrow:Colour(245, 245, 245, 255)
+ self.RightArrow:Colour(245, 245, 245, 255)
+ end
+ else
+ self.ItemText:Colour(163, 159, 148, 255)
+ self.LeftArrow:Colour(163, 159, 148, 255)
+ self.RightArrow:Colour(163, 159, 148, 255)
+ end
+
+ local Text = (type(self.Items[self._Index]) == "table") and tostring(self.Items[self._Index].Name) or tostring(self.Items[self._Index])
+ local Offset = MeasureStringWidth(Text, 0, 0.35)
+
+ self.ItemText:Text(Text)
+ self.LeftArrow:Position(378 - Offset + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.LeftArrow.Y)
+
+ if self:Selected() then
+ self.LeftArrow:Draw()
+ self.RightArrow:Draw()
+ self.ItemText:Position(403 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.ItemText.Y)
+ else
+ self.ItemText:Position(418 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, self.ItemText.Y)
+ end
+
+ self.ItemText:Draw()
+end
+
+--[[
+ UIMenuSliderItem.lua
+ Items
+--]]
+
+function UIMenuSliderItem.New(Text, Items, Index, Description, Divider)
+ if type(Items) ~= "table" then Items = {} end
+ if Index == 0 then Index = 1 end
+ local _UIMenuSliderItem = {
+ Base = UIMenuItem.New(Text or "", Description or ""),
+ Items = Items,
+ ShowDivider = tobool(Divider),
+ LeftArrow = Sprite.New("commonmenutu", "arrowleft", 0, 105, 15, 15),
+ RightArrow = Sprite.New("commonmenutu", "arrowright", 0, 105, 15, 15),
+ Background = UIResRectangle.New(0, 0, 150, 9, 15, 24, 33, 255),
+ Slider = UIResRectangle.New(0, 0, 75, 9, 72,109,149, 255),
+ Divider = UIResRectangle.New(0, 0, 2.5, 20, 245, 245, 245, 255),
+ _Index = tonumber(Index) or 1,
+ OnSliderChanged = function(menu, item, newindex) end,
+ OnSliderSelected = function(menu, item, newindex) end,
+ }
+ return setmetatable(_UIMenuSliderItem, UIMenuSliderItem)
+end
+
+function UIMenuSliderItem:SetParentMenu(Menu)
+ if Menu() == "UIMenu" then
+ self.Base.ParentMenu = Menu
+ else
+ return self.Base.ParentMenu
+ end
+end
+
+function UIMenuSliderItem:Position(Y)
+ if tonumber(Y) then
+ self.Background:Position(250 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 158.5 + self.Base._Offset.Y)
+ self.Slider:Position(250 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 158.5 + self.Base._Offset.Y)
+ self.Divider:Position(323.5 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, Y + 153 + self.Base._Offset.Y)
+ self.LeftArrow:Position(235 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 155.5 + Y + self.Base._Offset.Y)
+ self.RightArrow:Position(400 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 155.5 + Y + self.Base._Offset.Y)
+ self.Base:Position(Y)
+ end
+end
+
+function UIMenuSliderItem:Selected(bool)
+ if bool ~= nil then
+ self.Base._Selected = tobool(bool)
+ else
+ return self.Base._Selected
+ end
+end
+
+function UIMenuSliderItem:Hovered(bool)
+ if bool ~= nil then
+ self.Base._Hovered = tobool(bool)
+ else
+ return self.Base._Hovered
+ end
+end
+
+function UIMenuSliderItem:Enabled(bool)
+ if bool ~= nil then
+ self.Base._Enabled = tobool(bool)
+ else
+ return self.Base._Enabled
+ end
+end
+
+function UIMenuSliderItem:Description(str)
+ if tostring(str) and str ~= nil then
+ self.Base._Description = tostring(str)
+ else
+ return self.Base._Description
+ end
+end
+
+function UIMenuSliderItem:Offset(X, Y)
+ if tonumber(X) or tonumber(Y) then
+ if tonumber(X) then
+ self.Base._Offset.X = tonumber(X)
+ end
+ if tonumber(Y) then
+ self.Base._Offset.Y = tonumber(Y)
+ end
+ else
+ return self.Base._Offset
+ end
+end
+
+function UIMenuSliderItem:Text(Text)
+ if tostring(Text) and Text ~= nil then
+ self.Base.Text:Text(tostring(Text))
+ else
+ return self.Base.Text:Text()
+ end
+end
+
+function UIMenuSliderItem:Index(Index)
+ if tonumber(Index) then
+ if tonumber(Index) > #self.Items then
+ self._Index = 1
+ elseif tonumber(Index) < 1 then
+ self._Index = #self.Items
+ else
+ self._Index = tonumber(Index)
+ end
+ else
+ return self._Index
+ end
+end
+
+function UIMenuSliderItem:ItemToIndex(Item)
+ for i = 1, #self.Items do
+ if type(Item) == type(self.Items[i]) and Item == self.Items[i] then
+ return i
+ end
+ end
+end
+
+function UIMenuSliderItem:IndexToItem(Index)
+ if tonumber(Index) then
+ if tonumber(Index) == 0 then Index = 1 end
+ if self.Items[tonumber(Index)] then
+ return self.Items[tonumber(Index)]
+ end
+ end
+end
+
+function UIMenuSliderItem:SetLeftBadge()
+ error("This item does not support badges")
+end
+
+function UIMenuSliderItem:SetRightBadge()
+ error("This item does not support badges")
+end
+
+function UIMenuSliderItem:RightLabel()
+ error("This item does not support a right label")
+end
+
+function UIMenuSliderItem:Draw()
+ self.Base:Draw()
+
+ if self:Enabled() then
+ if self:Selected() then
+ self.LeftArrow:Colour(0, 0, 0, 255)
+ self.RightArrow:Colour(0, 0, 0, 255)
+ else
+ self.LeftArrow:Colour(245, 245, 245, 255)
+ self.RightArrow:Colour(245, 245, 245, 255)
+ end
+ else
+ self.LeftArrow:Colour(163, 159, 148, 255)
+ self.RightArrow:Colour(163, 159, 148, 255)
+ end
+
+ local Offset = ((self.Background.Width - self.Slider.Width)/(#self.Items - 1)) * (self._Index-1)
+
+ self.Slider:Position(250 + self.Base._Offset.X + Offset + self.Base.ParentMenu.WidthOffset, self.Slider.Y)
+
+ if self:Selected() then
+ self.LeftArrow:Draw()
+ self.RightArrow:Draw()
+ end
+
+ self.Background:Draw()
+ self.Slider:Draw()
+ if self.ShowDivider then
+ self.Divider:Draw()
+ end
+end
+
+--[[
+ UIMenuColouredItem.lua
+ Items
+--]]
+
+function UIMenuColouredItem.New(Text, Description, MainColour, HighlightColour)
+ if type(Colour) ~= "table" then Colour = {R = 0, G = 0, B = 0, A = 255} end
+ if type(HighlightColour) ~= "table" then Colour = {R = 255, G = 255, B = 255, A = 255} end
+ local _UIMenuColouredItem = {
+ Base = UIMenuItem.New(Text or "", Description or ""),
+ Rectangle = UIResRectangle.New(0, 0, 431, 38, MainColour.R, MainColour.G, MainColour.B, MainColour.A),
+ MainColour = MainColour,
+ HighlightColour = HighlightColour,
+ Activated = function(menu, item) end,
+ }
+ _UIMenuColouredItem.Base.SelectedSprite:Colour(HighlightColour.R, HighlightColour.G, HighlightColour.B, HighlightColour.A)
+ return setmetatable(_UIMenuColouredItem, UIMenuColouredItem)
+end
+
+function UIMenuColouredItem:SetParentMenu(Menu)
+ if Menu() == "UIMenu" then
+ self.Base.ParentMenu = Menu
+ else
+ return self.Base.ParentMenu
+ end
+end
+
+function UIMenuColouredItem:Position(Y)
+ if tonumber(Y) then
+ self.Base:Position(Y)
+ self.Rectangle:Position(self.Base._Offset.X, Y + 144 + self.Base._Offset.Y)
+ end
+end
+
+function UIMenuColouredItem:Selected(bool)
+ if bool ~= nil then
+ self.Base._Selected = tobool(bool)
+ else
+ return self.Base._Selected
+ end
+end
+
+function UIMenuColouredItem:Hovered(bool)
+ if bool ~= nil then
+ self.Base._Hovered = tobool(bool)
+ else
+ return self.Base._Hovered
+ end
+end
+
+function UIMenuColouredItem:Enabled(bool)
+ if bool ~= nil then
+ self.Base._Enabled = tobool(bool)
+ else
+ return self.Base._Enabled
+ end
+end
+
+function UIMenuColouredItem:Description(str)
+ if tostring(str) and str ~= nil then
+ self.Base._Description = tostring(str)
+ else
+ return self.Base._Description
+ end
+end
+
+function UIMenuColouredItem:Offset(X, Y)
+ if tonumber(X) or tonumber(Y) then
+ if tonumber(X) then
+ self.Base._Offset.X = tonumber(X)
+ end
+ if tonumber(Y) then
+ self.Base._Offset.Y = tonumber(Y)
+ end
+ else
+ return self.Base._Offset
+ end
+end
+
+function UIMenuColouredItem:Text(Text)
+ if tostring(Text) and Text ~= nil then
+ self.Base.Text:Text(tostring(Text))
+ else
+ return self.Base.Text:Text()
+ end
+end
+
+function UIMenuColouredItem:RightLabel(Text, MainColour, HighlightColour)
+ if tostring(Text) and Text ~= nil then
+ if type(MainColour) == "table" then
+ self.Base.Label.MainColour = MainColour
+ end
+ if type(HighlightColour) == "table" then
+ self.Base.Label.HighlightColour = HighlightColour
+ end
+ self.Base.Label.Text:Text(tostring(Text))
+ else
+ return self.Base.Label.Text:Text()
+ end
+end
+
+function UIMenuColouredItem:SetLeftBadge(Badge)
+ if tonumber(Badge) then
+ self.Base.LeftBadge.Badge = tonumber(Badge)
+ end
+end
+
+function UIMenuColouredItem:SetRightBadge(Badge)
+ if tonumber(Badge) then
+ self.Base.RightBadge.Badge = tonumber(Badge)
+ end
+end
+
+function UIMenuColouredItem:Draw()
+ self.Rectangle:Size(431 + self.ParentMenu.WidthOffset, self.Rectangle.Height)
+ self.Rectangle:Draw()
+ self.Base:Draw()
+end
+
+--[[
+ UIMenuProgressItem.lua
+ Items
+--]]
+
+function UIMenuProgressItem.New(Text, Items, Index, Description, Counter)
+ if type(Items) ~= "table" then Items = {} end
+ if Index == 0 then Index = 1 end
+ local _UIMenuProgressItem = {
+ Base = UIMenuItem.New(Text or "", Description or ""),
+ Data = {
+ Items = Items,
+ Counter = tobool(Counter),
+ Max = 407.5,
+ Index = tonumber(Index) or 1,
+ },
+ Background = UIResRectangle.New(0, 0, 415, 20),
+ Bar = UIResRectangle.New(0, 0, 407.5, 12.5),
+ OnProgressChanged = function(menu, item, newindex) end,
+ OnProgressSelected = function(menu, item, newindex) end,
+ }
+
+ _UIMenuProgressItem.Base.Rectangle.Height = 60
+ _UIMenuProgressItem.Base.SelectedSprite.Height = 60
+
+ if _UIMenuProgressItem.Data.Counter then
+ _UIMenuProgressItem.Base:RightLabel(_UIMenuProgressItem.Data.Index.."/"..#_UIMenuProgressItem.Data.Items)
+ else
+ _UIMenuProgressItem.Base:RightLabel((type(_UIMenuProgressItem.Data.Items[_UIMenuProgressItem.Data.Index]) == "table") and tostring(_UIMenuProgressItem.Data.Items[_UIMenuProgressItem.Data.Index].Name) or tostring(_UIMenuProgressItem.Data.Items[_UIMenuProgressItem.Data.Index]))
+ end
+
+ _UIMenuProgressItem.Bar.Width = _UIMenuProgressItem.Data.Index/#_UIMenuProgressItem.Data.Items * _UIMenuProgressItem.Data.Max
+
+ return setmetatable(_UIMenuProgressItem, UIMenuProgressItem)
+end
+
+function UIMenuProgressItem:SetParentMenu(Menu)
+ if Menu() == "UIMenu" then
+ self.Base.ParentMenu = Menu
+ else
+ return self.Base.ParentMenu
+ end
+end
+
+function UIMenuProgressItem:Position(Y)
+ if tonumber(Y) then
+ self.Base:Position(Y)
+ self.Background:Position(8 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 177 + Y + self.Base._Offset.Y)
+ self.Bar:Position(11.75 + self.Base._Offset.X + self.Base.ParentMenu.WidthOffset, 180.75 + Y + self.Base._Offset.Y)
+ end
+end
+
+function UIMenuProgressItem:Selected(bool)
+ if bool ~= nil then
+ self.Base._Selected = tobool(bool)
+ else
+ return self.Base._Selected
+ end
+end
+
+function UIMenuProgressItem:Hovered(bool)
+ if bool ~= nil then
+ self.Base._Hovered = tobool(bool)
+ else
+ return self.Base._Hovered
+ end
+end
+
+function UIMenuProgressItem:Enabled(bool)
+ if bool ~= nil then
+ self.Base._Enabled = tobool(bool)
+ else
+ return self.Base._Enabled
+ end
+end
+
+function UIMenuProgressItem:Description(str)
+ if tostring(str) and str ~= nil then
+ self.Base._Description = tostring(str)
+ else
+ return self.Base._Description
+ end
+end
+
+function UIMenuProgressItem:Offset(X, Y)
+ if tonumber(X) or tonumber(Y) then
+ if tonumber(X) then
+ self.Base._Offset.X = tonumber(X)
+ end
+ if tonumber(Y) then
+ self.Base._Offset.Y = tonumber(Y)
+ end
+ else
+ return self.Base._Offset
+ end
+end
+
+function UIMenuProgressItem:Text(Text)
+ if tostring(Text) and Text ~= nil then
+ self.Base.Text:Text(tostring(Text))
+ else
+ return self.Base.Text:Text()
+ end
+end
+
+function UIMenuProgressItem:Index(Index)
+ if tonumber(Index) then
+ if tonumber(Index) > #self.Data.Items then
+ self.Data.Index = 1
+ elseif tonumber(Index) < 1 then
+ self.Data.Index = #self.Data.Items
+ else
+ self.Data.Index = tonumber(Index)
+ end
+
+ if self.Data.Counter then
+ self.Base:RightLabel(self.Data.Index.."/"..#self.Data.Items)
+ else
+ self.Base:RightLabel((type(self.Data.Items[self.Data.Index]) == "table") and tostring(self.Data.Items[self.Data.Index].Name) or tostring(self.Data.Items[self.Data.Index]))
+ end
+
+ self.Bar.Width = self.Data.Index/#self.Data.Items * self.Data.Max
+ else
+ return self.Data.Index
+ end
+end
+
+function UIMenuProgressItem:ItemToIndex(Item)
+ for i = 1, #self.Data.Items do
+ if type(Item) == type(self.Data.Items[i]) and Item == self.Data.Items[i] then
+ return i
+ elseif type(self.Data.Items[i]) == "table" and (type(Item) == type(self.Data.Items[i].Name) or type(Item) == type(self.Data.Items[i].Value)) and (Item == self.Data.Items[i].Name or Item == self.Data.Items[i].Value) then
+ return i
+ end
+ end
+end
+
+function UIMenuProgressItem:IndexToItem(Index)
+ if tonumber(Index) then
+ if tonumber(Index) == 0 then Index = 1 end
+ if self.Data.Items[tonumber(Index)] then
+ return self.Data.Items[tonumber(Index)]
+ end
+ end
+end
+
+function UIMenuProgressItem:SetLeftBadge()
+ error("This item does not support badges")
+end
+
+function UIMenuProgressItem:SetRightBadge()
+ error("This item does not support badges")
+end
+
+function UIMenuProgressItem:RightLabel()
+ error("This item does not support a right label")
+end
+
+function UIMenuProgressItem:CalculateProgress(CursorX)
+ local Progress = CursorX - self.Bar.X
+ self:Index(math.round(#self.Data.Items * (((Progress >= 0 and Progress <= self.Data.Max) and Progress or ((Progress < 0) and 0 or self.Data.Max))/self.Data.Max)))
+end
+
+function UIMenuProgressItem:Draw()
+ self.Base:Draw()
+
+ if self.Base._Selected then
+ self.Background:Colour(table.unpack(Colours.Black))
+ self.Bar:Colour(table.unpack(Colours.White))
+ else
+ self.Background:Colour(table.unpack(Colours.White))
+ self.Bar:Colour(table.unpack(Colours.Black))
+ end
+
+ self.Background:Draw()
+ self.Bar:Draw()
+end
+
+--[[
+ UIMenuHeritageWindow.lua
+ Windows
+--]]
+
+function UIMenuHeritageWindow.New(Mum, Dad)
+ if not tonumber(Mum) then Mum = 0 end
+ if not (Mum >= 0 and Mum <= 21) then Mum = 0 end
+ if not tonumber(Dad) then Dad = 0 end
+ if not (Dad >= 0 and Dad <= 23) then Dad = 0 end
+ _UIMenuHeritageWindow = {
+ Background = Sprite.New("pause_menu_pages_char_mom_dad", "mumdadbg", 0, 0, 431, 228), -- Background is required, must be a sprite or a rectangle.
+ MumSprite = Sprite.New("char_creator_portraits", ((Mum < 21) and "female_"..Mum or "special_female_"..(tonumber(string.sub(Mum, 2, 2)) - 1)), 0, 0, 228, 228),
+ DadSprite = Sprite.New("char_creator_portraits", ((Dad < 21) and "male_"..Dad or "special_male_"..(tonumber(string.sub(Dad, 2, 2)) - 1)), 0, 0, 228, 228),
+ Mum = Mum,
+ Dad = Dad,
+ _Offset = {X = 0, Y = 0}, -- required
+ ParentMenu = nil, -- required
+ }
+ return setmetatable(_UIMenuHeritageWindow, UIMenuHeritageWindow)
+end
+
+function UIMenuHeritageWindow:SetParentMenu(Menu) -- required
+ if Menu() == "UIMenu" then
+ self.ParentMenu = Menu
+ else
+ return self.ParentMenu
+ end
+end
+
+function UIMenuHeritageWindow:Offset(X, Y) -- required
+ if tonumber(X) or tonumber(Y) then
+ if tonumber(X) then
+ self._Offset.X = tonumber(X)
+ end
+ if tonumber(Y) then
+ self._Offset.Y = tonumber(Y)
+ end
+ else
+ return self._Offset
+ end
+end
+
+function UIMenuHeritageWindow:Position(Y) -- required
+ if tonumber(Y) then
+ self.Background:Position(self._Offset.X, 144 + Y + self._Offset.Y)
+ self.MumSprite:Position(self._Offset.X + (self.ParentMenu.WidthOffset/2) + 25, 144 + Y + self._Offset.Y)
+ self.DadSprite:Position(self._Offset.X + (self.ParentMenu.WidthOffset/2) + 195, 144 + Y + self._Offset.Y)
+ end
+end
+
+function UIMenuHeritageWindow:Index(Mum, Dad)
+ if not tonumber(Mum) then Mum = self.Mum end
+ if not (Mum >= 0 and Mum <= 21) then Mum = self.Mum end
+ if not tonumber(Dad) then Dad = self.Dad end
+ if not (Dad >= 0 and Dad <= 23) then Dad = self.Dad end
+
+ self.Mum = Mum
+ self.Dad = Dad
+
+ self.MumSprite.TxtName = ((self.Mum < 21) and "female_"..self.Mum or "special_female_"..(tonumber(string.sub(Mum, 2, 2)) - 1))
+ self.DadSprite.TxtName = ((self.Dad < 21) and "male_"..self.Dad or "special_male_"..(tonumber(string.sub(Dad, 2, 2)) - 1))
+end
+
+function UIMenuHeritageWindow:Draw() -- required
+ self.Background:Size(431 + self.ParentMenu.WidthOffset, 228)
+ self.Background:Draw()
+ self.DadSprite:Draw()
+ self.MumSprite:Draw()
+end
+
+--[[
+ UIMenuGridPanel.lua
+ Panels
+--]]
+
+UIMenuGridPanel = setmetatable({}, UIMenuGridPanel)
+UIMenuGridPanel.__index = UIMenuGridPanel
+UIMenuGridPanel.__call = function() return "UIMenuPanel", "UIMenuGridPanel" end
+
+function UIMenuGridPanel.New(TopText, LeftText, RightText, BottomText)
+ _UIMenuGridPanel = {
+ Data = {
+ Enabled = true,
+ },
+ Background = Sprite.New("commonmenu", "gradient_bgd", 0, 0, 431, 275),
+ Grid = Sprite.New("pause_menu_pages_char_mom_dad", "nose_grid", 0, 0, 200, 200, 0),
+ Circle = Sprite.New("mpinventory","in_world_circle", 0, 0, 20, 20, 0),
+ Audio = {Slider = "CONTINUOUS_SLIDER", Library = "HUD_FRONTEND_DEFAULT_SOUNDSET", Id = nil},
+ ParentItem = nil,
+ Text = {
+ Top = UIResText.New(TopText or "Top", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
+ Left = UIResText.New(LeftText or "Left", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
+ Right = UIResText.New(RightText or "Right", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
+ Bottom = UIResText.New(BottomText or "Bottom", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
+ },
+ }
+ return setmetatable(_UIMenuGridPanel, UIMenuGridPanel)
+end
+
+function UIMenuGridPanel:SetParentItem(Item) -- required
+ if Item() == "UIMenuItem" then
+ self.ParentItem = Item
+ else
+ return self.ParentItem
+ end
+end
+
+function UIMenuGridPanel:Enabled(Enabled)
+ if type(Enabled) == "boolean" then
+ self.Data.Enabled = Enabled
+ else
+ return self.Data.Enabled
+ end
+end
+
+function UIMenuGridPanel:CirclePosition(X, Y)
+ if tonumber(X) and tonumber(Y) then
+ self.Circle.X = (self.Grid.X + 20) + ((self.Grid.Width - 40) * ((X >= 0.0 and X <= 1.0) and X or 0.0)) - (self.Circle.Width/2)
+ self.Circle.Y = (self.Grid.Y + 20) + ((self.Grid.Height - 40) * ((Y >= 0.0 and Y <= 1.0) and Y or 0.0)) - (self.Circle.Height/2)
+ else
+ return math.round((self.Circle.X - (self.Grid.X + 20) + (self.Circle.Width/2))/(self.Grid.Width - 40), 2), math.round((self.Circle.Y - (self.Grid.Y + 20) + (self.Circle.Height/2))/(self.Grid.Height - 40), 2)
+ end
+end
+
+function UIMenuGridPanel:Position(Y) -- required
+ if tonumber(Y) then
+ local ParentOffsetX, ParentOffsetWidth = self.ParentItem:Offset().X, self.ParentItem:SetParentMenu().WidthOffset
+
+ self.Background:Position(ParentOffsetX, Y)
+ self.Grid:Position(ParentOffsetX + 115.5 + (ParentOffsetWidth/2), 37.5 + Y)
+ self.Text.Top:Position(ParentOffsetX + 215.5 + (ParentOffsetWidth/2), 5 + Y)
+ self.Text.Left:Position(ParentOffsetX + 57.75 + (ParentOffsetWidth/2), 120 + Y)
+ self.Text.Right:Position(ParentOffsetX + 373.25 + (ParentOffsetWidth/2), 120 + Y)
+ self.Text.Bottom:Position(ParentOffsetX + 215.5 + (ParentOffsetWidth/2), 240 + Y)
+
+ if not self.CircleLocked then
+ self.CircleLocked = true
+ self:CirclePosition(0.5, 0.5)
+ end
+ end
+end
+
+function UIMenuGridPanel:UpdateParent(X, Y)
+ local _, ParentType = self.ParentItem()
+ if ParentType == "UIMenuListItem" then
+ local PanelItemIndex = self.ParentItem:FindPanelItem()
+ if PanelItemIndex then
+ self.ParentItem.Items[PanelItemIndex].Value[self.ParentItem:FindPanelIndex(self)] = {X = X, Y = Y}
+ self.ParentItem:Index(PanelItemIndex)
+ self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
+ self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
+ else
+ local PanelIndex = self.ParentItem:FindPanelIndex(self)
+ for Index = 1, #self.ParentItem.Items do
+ if type(self.ParentItem.Items[Index]) == "table" then
+ if not self.ParentItem.Items[Index].Panels then self.ParentItem.Items[Index].Panels = {} end
+ self.ParentItem.Items[Index].Panels[PanelIndex] = {X = X, Y = Y}
+ else
+ self.ParentItem.Items[Index] = {Name = tostring(self.ParentItem.Items[Index]), Value = self.ParentItem.Items[Index], Panels = {[PanelIndex] = {X = X, Y = Y}}}
+ end
+ end
+ self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
+ self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
+ end
+ elseif ParentType == "UIMenuItem" then
+ self.ParentItem.ActivatedPanel(self.ParentItem.ParentMenu, self.ParentItem, self, {X = X, Y = Y})
+ end
+end
+
+function UIMenuGridPanel:Functions()
+ local SafeZone = {X = 0, Y = 0}
+ if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then
+ SafeZone = GetSafeZoneBounds()
+ end
+
+ if IsMouseInBounds(self.Grid.X + 20 + SafeZone.X, self.Grid.Y + 20 + SafeZone.Y, self.Grid.Width - 40, self.Grid.Height - 40) then
+ if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then
+ if not self.Pressed then
+ self.Pressed = true
+ Citizen.CreateThread(function()
+ self.Audio.Id = GetSoundId()
+ PlaySoundFrontend(self.Audio.Id, self.Audio.Slider, self.Audio.Library, 1)
+ while IsDisabledControlPressed(0, 24) and IsMouseInBounds(self.Grid.X + 20 + SafeZone.X, self.Grid.Y + 20 + SafeZone.Y, self.Grid.Width - 40, self.Grid.Height - 40) do
+ Citizen.Wait(0)
+ local CursorX, CursorY = math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X - (self.Circle.Width/2), math.round(GetControlNormal(0, 240) * 1080) - SafeZone.Y - (self.Circle.Height/2)
+
+ self.Circle:Position(((CursorX > (self.Grid.X + 10 + self.Grid.Width - 40)) and (self.Grid.X + 10 + self.Grid.Width - 40) or ((CursorX < (self.Grid.X + 20 - (self.Circle.Width/2))) and (self.Grid.X + 20 - (self.Circle.Width/2)) or CursorX)), ((CursorY > (self.Grid.Y + 10 + self.Grid.Height - 40)) and (self.Grid.Y + 10 + self.Grid.Height - 40) or ((CursorY < (self.Grid.Y + 20 - (self.Circle.Height/2))) and (self.Grid.Y + 20 - (self.Circle.Height/2)) or CursorY)))
+ end
+ StopSound(self.Audio.Id)
+ ReleaseSoundId(self.Audio.Id)
+ self.Pressed = false
+ end)
+ Citizen.CreateThread(function()
+ while IsDisabledControlPressed(0, 24) and IsMouseInBounds(self.Grid.X + 20 + SafeZone.X, self.Grid.Y + 20 + SafeZone.Y, self.Grid.Width - 40, self.Grid.Height - 40) do
+ Citizen.Wait(75)
+ local ResultX, ResultY = math.round((self.Circle.X - (self.Grid.X + 20) + (self.Circle.Width/2))/(self.Grid.Width - 40), 2), math.round((self.Circle.Y - (self.Grid.Y + 20) + (self.Circle.Height/2))/(self.Grid.Height - 40), 2)
+
+ self:UpdateParent((((ResultX >= 0.0 and ResultX <= 1.0) and ResultX or ((ResultX <= 0) and 0.0) or 1.0) * 2) - 1, (((ResultY >= 0.0 and ResultY <= 1.0) and ResultY or ((ResultY <= 0) and 0.0) or 1.0) * 2) - 1)
+ end
+ end)
+ end
+ end
+ end
+end
+
+function UIMenuGridPanel:Draw() -- required
+ if self.Data.Enabled then
+ self.Background:Size(431 + self.ParentItem:SetParentMenu().WidthOffset, 275)
+
+ self.Background:Draw()
+ self.Grid:Draw()
+ self.Circle:Draw()
+ self.Text.Top:Draw()
+ self.Text.Left:Draw()
+ self.Text.Right:Draw()
+ self.Text.Bottom:Draw()
+ self:Functions()
+ end
+end
+
+--[[
+ UIMenuColourPanel.lua
+ Panels
+--]]
+
+UIMenuColourPanel = setmetatable({}, UIMenuColourPanel)
+UIMenuColourPanel.__index = UIMenuColourPanel
+UIMenuColourPanel.__call = function() return "UIMenuPanel", "UIMenuColourPanel" end
+
+function UIMenuColourPanel.New(Title, Colours)
+ _UIMenuColourPanel = {
+ Data = {
+ Pagination = {
+ Min = 1,
+ Max = 8,
+ Total = 8,
+ },
+ Index = 1000,
+ Items = Colours,
+ Title = Title or "Title",
+ Enabled = true,
+ Value = 1,
+ },
+ Background = Sprite.New("commonmenu", "gradient_bgd", 0, 0, 431, 112),
+ Bar = {},
+ LeftArrow = Sprite.New("commonmenu", "arrowleft", 0, 0, 30, 30),
+ RightArrow = Sprite.New("commonmenu", "arrowright", 0, 0, 30, 30),
+ SelectedRectangle = UIResRectangle.New(0, 0, 44.5, 8),
+ Text = UIResText.New(Title.." (1 of "..#Colours..")" or "Title".." (1 of "..#Colours..")", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
+ ParentItem = nil,
+ }
+
+ for Index = 1, #Colours do
+ if Index < 10 then
+ table.insert(_UIMenuColourPanel.Bar, UIResRectangle.New(0, 0, 44.5, 44.5, table.unpack(Colours[Index])))
+ else
+ break
+ end
+ end
+
+ if #_UIMenuColourPanel.Data.Items ~= 0 then
+ _UIMenuColourPanel.Data.Index = 1000 - (1000 % #_UIMenuColourPanel.Data.Items)
+ _UIMenuColourPanel.Data.Pagination.Max = _UIMenuColourPanel.Data.Pagination.Total + 1
+ _UIMenuColourPanel.Data.Pagination.Min = 0
+ end
+ return setmetatable(_UIMenuColourPanel, UIMenuColourPanel)
+end
+
+function UIMenuColourPanel:SetParentItem(Item) -- required
+ if Item() == "UIMenuItem" then
+ self.ParentItem = Item
+ else
+ return self.ParentItem
+ end
+end
+
+function UIMenuColourPanel:Enabled(Enabled)
+ if type(Enabled) == "boolean" then
+ self.Data.Enabled = Enabled
+ else
+ return self.Data.Enabled
+ end
+end
+
+function UIMenuColourPanel:Position(Y) -- required
+ if tonumber(Y) then
+ local ParentOffsetX, ParentOffsetWidth = self.ParentItem:Offset().X, self.ParentItem:SetParentMenu().WidthOffset
+
+ self.Background:Position(ParentOffsetX, Y)
+ for Index = 1, #self.Bar do
+ self.Bar[Index]:Position(15 + (44.5 * (Index - 1)) + ParentOffsetX + (ParentOffsetWidth/2), 55 + Y)
+ end
+ self.SelectedRectangle:Position(15 + (44.5 * ((self:CurrentSelection() - self.Data.Pagination.Min) - 1)) + ParentOffsetX + (ParentOffsetWidth/2), 47 + Y)
+ self.LeftArrow:Position(7.5 + ParentOffsetX + (ParentOffsetWidth/2), 15 + Y)
+ self.RightArrow:Position(393.5 + ParentOffsetX + (ParentOffsetWidth/2), 15 + Y)
+ self.Text:Position(215.5 + ParentOffsetX + (ParentOffsetWidth/2), 15 + Y)
+ end
+end
+
+function UIMenuColourPanel:CurrentSelection(value, PreventUpdate)
+ if tonumber(value) then
+ if #self.Data.Items == 0 then
+ self.Data.Index = 0
+ end
+
+ self.Data.Index = 1000000 - (1000000 % #self.Data.Items) + tonumber(value)
+
+ if self:CurrentSelection() > self.Data.Pagination.Max then
+ self.Data.Pagination.Min = self:CurrentSelection() - (self.Data.Pagination.Total + 1)
+ self.Data.Pagination.Max = self:CurrentSelection()
+ elseif self:CurrentSelection() < self.Data.Pagination.Min then
+ self.Data.Pagination.Min = self:CurrentSelection() - 1
+ self.Data.Pagination.Max = self:CurrentSelection() + (self.Data.Pagination.Total + 1)
+ end
+
+ self:UpdateSelection(PreventUpdate)
+ else
+ if #self.Data.Items == 0 then
+ return 1
+ else
+ if self.Data.Index % #self.Data.Items == 0 then
+ return 1
+ else
+ return self.Data.Index % #self.Data.Items + 1
+ end
+ end
+ end
+end
+
+function UIMenuColourPanel:UpdateParent(Colour)
+ local _, ParentType = self.ParentItem()
+ if ParentType == "UIMenuListItem" then
+ local PanelItemIndex = self.ParentItem:FindPanelItem()
+ local PanelIndex = self.ParentItem:FindPanelIndex(self)
+ if PanelItemIndex then
+ self.ParentItem.Items[PanelItemIndex].Value[PanelIndex] = Colour
+ self.ParentItem:Index(PanelItemIndex)
+ self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
+ self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
+ else
+ for Index = 1, #self.ParentItem.Items do
+ if type(self.ParentItem.Items[Index]) == "table" then
+ if not self.ParentItem.Items[Index].Panels then self.ParentItem.Items[Index].Panels = {} end
+ self.ParentItem.Items[Index].Panels[PanelIndex] = Colour
+ else
+ self.ParentItem.Items[Index] = {Name = tostring(self.ParentItem.Items[Index]), Value = self.ParentItem.Items[Index], Panels = {[PanelIndex] = Colour}}
+ end
+ end
+ self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
+ self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
+ end
+ elseif ParentType == "UIMenuItem" then
+ self.ParentItem.ActivatedPanel(self.ParentItem.ParentMenu, self.ParentItem, self, Colour)
+ end
+end
+
+function UIMenuColourPanel:UpdateSelection(PreventUpdate)
+ local CurrentSelection = self:CurrentSelection()
+ if not PreventUpdate then
+ self:UpdateParent(CurrentSelection)
+ end
+ self.SelectedRectangle:Position(15 + (44.5 * ((CurrentSelection - self.Data.Pagination.Min) - 1)) + self.ParentItem:Offset().X, self.SelectedRectangle.Y)
+ for Index = 1, 9 do
+ self.Bar[Index]:Colour(table.unpack(self.Data.Items[self.Data.Pagination.Min + Index]))
+ end
+ self.Text:Text(self.Data.Title.." ("..CurrentSelection.." of "..#self.Data.Items..")")
+end
+
+function UIMenuColourPanel:Functions()
+
+ local SafeZone = {X = 0, Y = 0}
+ if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then
+ SafeZone = GetSafeZoneBounds()
+ end
+
+
+ if IsMouseInBounds(self.LeftArrow.X + SafeZone.X, self.LeftArrow.Y + SafeZone.Y, self.LeftArrow.Width, self.LeftArrow.Height) then
+ if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then
+ if #self.Data.Items > self.Data.Pagination.Total + 1 then
+ if self:CurrentSelection() <= self.Data.Pagination.Min + 1 then
+ if self:CurrentSelection() == 1 then
+ self.Data.Pagination.Min = #self.Data.Items - (self.Data.Pagination.Total + 1)
+ self.Data.Pagination.Max = #self.Data.Items
+ self.Data.Index = 1000 - (1000 % #self.Data.Items)
+ self.Data.Index = self.Data.Index + (#self.Data.Items - 1)
+ self:UpdateSelection()
+ else
+ self.Data.Pagination.Min = self.Data.Pagination.Min - 1
+ self.Data.Pagination.Max = self.Data.Pagination.Max - 1
+ self.Data.Index = self.Data.Index - 1
+ self:UpdateSelection()
+ end
+ else
+ self.Data.Index = self.Data.Index - 1
+ self:UpdateSelection()
+ end
+ else
+ self.Data.Index = self.Data.Index - 1
+ self:UpdateSelection()
+ end
+ end
+ end
+
+ if IsMouseInBounds(self.RightArrow.X + SafeZone.X, self.RightArrow.Y + SafeZone.Y, self.RightArrow.Width, self.RightArrow.Height) then
+ if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then
+ if #self.Data.Items > self.Data.Pagination.Total + 1 then
+ if self:CurrentSelection() >= self.Data.Pagination.Max then
+ if self:CurrentSelection() == #self.Data.Items then
+ self.Data.Pagination.Min = 0
+ self.Data.Pagination.Max = self.Data.Pagination.Total + 1
+ self.Data.Index = 1000 - (1000 % #self.Data.Items)
+ self:UpdateSelection()
+ else
+ self.Data.Pagination.Max = self.Data.Pagination.Max + 1
+ self.Data.Pagination.Min = self.Data.Pagination.Max - (self.Data.Pagination.Total + 1)
+ self.Data.Index = self.Data.Index + 1
+ self:UpdateSelection()
+ end
+ else
+ self.Data.Index = self.Data.Index + 1
+ self:UpdateSelection()
+ end
+ else
+ self.Data.Index = self.Data.Index + 1
+ self:UpdateSelection()
+ end
+ end
+ end
+
+ for Index = 1, #self.Bar do
+ if IsMouseInBounds(self.Bar[Index].X + SafeZone.X, self.Bar[Index].Y + SafeZone.Y, self.Bar[Index].Width, self.Bar[Index].Height) then
+ if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then
+ self:CurrentSelection(self.Data.Pagination.Min + Index - 1)
+ end
+ end
+ end
+end
+
+function UIMenuColourPanel:Draw() -- required
+ if self.Data.Enabled then
+ self.Background:Size(431 + self.ParentItem:SetParentMenu().WidthOffset, 112)
+
+ self.Background:Draw()
+ self.LeftArrow:Draw()
+ self.RightArrow:Draw()
+ self.Text:Draw()
+ self.SelectedRectangle:Draw()
+ for Index = 1, #self.Bar do
+ self.Bar[Index]:Draw()
+ end
+ self:Functions()
+ end
+end
+
+--[[
+ UIMenuPercentagePanel.lua
+ Panels
+--]]
+
+UIMenuPercentagePanel = setmetatable({}, UIMenuPercentagePanel)
+UIMenuPercentagePanel.__index = UIMenuPercentagePanel
+UIMenuPercentagePanel.__call = function() return "UIMenuPanel", "UIMenuPercentagePanel" end
+
+function UIMenuPercentagePanel.New(MinText, MaxText)
+ _UIMenuPercentagePanel = {
+ Data = {
+ Enabled = true,
+ },
+ Background = Sprite.New("commonmenu", "gradient_bgd", 0, 0, 431, 76),
+ ActiveBar = UIResRectangle.New(0, 0, 413, 10, 245, 245, 245, 255),
+ BackgroundBar = UIResRectangle.New(0, 0, 413, 10, 87, 87, 87, 255),
+ Text = {
+ Min = UIResText.New(MinText or "0%", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
+ Max = UIResText.New("100%", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
+ Title = UIResText.New(MaxText or "Opacity", 0, 0, 0.35, 255, 255, 255, 255, 0, "Centre"),
+ },
+ Audio = {Slider = "CONTINUOUS_SLIDER", Library = "HUD_FRONTEND_DEFAULT_SOUNDSET", Id = nil},
+ ParentItem = nil,
+ }
+
+ return setmetatable(_UIMenuPercentagePanel, UIMenuPercentagePanel)
+end
+
+function UIMenuPercentagePanel:SetParentItem(Item) -- required
+ if Item() == "UIMenuItem" then
+ self.ParentItem = Item
+ else
+ return self.ParentItem
+ end
+end
+
+function UIMenuPercentagePanel:Enabled(Enabled)
+ if type(Enabled) == "boolean" then
+ self.Data.Enabled = Enabled
+ else
+ return self.Data.Enabled
+ end
+end
+
+function UIMenuPercentagePanel:Position(Y) -- required
+ if tonumber(Y) then
+ local ParentOffsetX, ParentOffsetWidth = self.ParentItem:Offset().X, self.ParentItem:SetParentMenu().WidthOffset
+ self.Background:Position(ParentOffsetX, Y)
+ self.ActiveBar:Position(ParentOffsetX + (ParentOffsetWidth/2) + 9, 50 + Y)
+ self.BackgroundBar:Position(ParentOffsetX + (ParentOffsetWidth/2) + 9, 50 + Y)
+ self.Text.Min:Position(ParentOffsetX + (ParentOffsetWidth/2) + 25, 15 + Y)
+ self.Text.Max:Position(ParentOffsetX + (ParentOffsetWidth/2) + 398, 15 + Y)
+ self.Text.Title:Position(ParentOffsetX + (ParentOffsetWidth/2) + 215.5, 15 + Y)
+ end
+end
+
+function UIMenuPercentagePanel:Percentage(Value)
+ if tonumber(Value) then
+ local Percent = ((Value < 0.0) and 0.0) or ((Value > 1.0) and 1.0 or Value)
+ self.ActiveBar:Size(self.BackgroundBar.Width * Percent, self.ActiveBar.Height)
+ else
+ local SafeZone = {X = 0, Y = 0}
+ if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then
+ SafeZone = GetSafeZoneBounds()
+ end
+
+ local Progress = (math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.ActiveBar.X
+ return math.round(((Progress >= 0 and Progress <= 413) and Progress or ((Progress < 0) and 0 or 413))/self.BackgroundBar.Width, 2)
+ end
+end
+
+function UIMenuPercentagePanel:UpdateParent(Percentage)
+ local _, ParentType = self.ParentItem()
+ if ParentType == "UIMenuListItem" then
+ local PanelItemIndex = self.ParentItem:FindPanelItem()
+ if PanelItemIndex then
+ self.ParentItem.Items[PanelItemIndex].Value[self.ParentItem:FindPanelIndex(self)] = Percentage
+ self.ParentItem:Index(PanelItemIndex)
+ self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
+ self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
+ else
+ local PanelIndex = self.ParentItem:FindPanelIndex(self)
+ for Index = 1, #self.ParentItem.Items do
+ if type(self.ParentItem.Items[Index]) == "table" then
+ if not self.ParentItem.Items[Index].Panels then self.ParentItem.Items[Index].Panels = {} end
+ self.ParentItem.Items[Index].Panels[PanelIndex] = Percentage
+ else
+ self.ParentItem.Items[Index] = {Name = tostring(self.ParentItem.Items[Index]), Value = self.ParentItem.Items[Index], Panels = {[PanelIndex] = Percentage}}
+ end
+ end
+ self.ParentItem.Base.ParentMenu.OnListChange(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
+ self.ParentItem.OnListChanged(self.ParentItem.Base.ParentMenu, self.ParentItem, self.ParentItem._Index)
+ end
+ elseif ParentType == "UIMenuItem" then
+ self.ParentItem.ActivatedPanel(self.ParentItem.ParentMenu, self.ParentItem, self, Percentage)
+ end
+end
+
+function UIMenuPercentagePanel:Functions()
+
+ local SafeZone = {X = 0, Y = 0}
+ if self.ParentItem:SetParentMenu().Settings.ScaleWithSafezone then
+ SafeZone = GetSafeZoneBounds()
+ end
+
+ if IsMouseInBounds(self.BackgroundBar.X + SafeZone.X, self.BackgroundBar.Y - 4 + SafeZone.Y, self.BackgroundBar.Width, self.BackgroundBar.Height + 8) then
+ if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then
+ if not self.Pressed then
+ self.Pressed = true
+ Citizen.CreateThread(function()
+ self.Audio.Id = GetSoundId()
+ PlaySoundFrontend(self.Audio.Id, self.Audio.Slider, self.Audio.Library, 1)
+ while IsDisabledControlPressed(0, 24) and IsMouseInBounds(self.BackgroundBar.X + SafeZone.X, self.BackgroundBar.Y - 4 + SafeZone.Y, self.BackgroundBar.Width, self.BackgroundBar.Height + 8) do
+ Citizen.Wait(0)
+ local Progress = (math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.ActiveBar.X
+ self.ActiveBar:Size(((Progress >= 0 and Progress <= 413) and Progress or ((Progress < 0) and 0 or 413)), self.ActiveBar.Height)
+ end
+ StopSound(self.Audio.Id)
+ ReleaseSoundId(self.Audio.Id)
+ self.Pressed = false
+ end)
+ Citizen.CreateThread(function()
+ while IsDisabledControlPressed(0, 24) and IsMouseInBounds(self.BackgroundBar.X + SafeZone.X, self.BackgroundBar.Y - 4 + SafeZone.Y, self.BackgroundBar.Width, self.BackgroundBar.Height + 8) do
+ Citizen.Wait(75)
+ local Progress = (math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X) - self.ActiveBar.X
+ self:UpdateParent(math.round(((Progress >= 0 and Progress <= 413) and Progress or ((Progress < 0) and 0 or 413))/self.BackgroundBar.Width, 2))
+ end
+ end)
+ end
+ end
+ end
+end
+
+function UIMenuPercentagePanel:Draw() -- required
+ if self.Data.Enabled then
+ self.Background:Size(431 + self.ParentItem:SetParentMenu().WidthOffset, 76)
+ self.Background:Draw()
+ self.BackgroundBar:Draw()
+ self.ActiveBar:Draw()
+ self.Text.Min:Draw()
+ self.Text.Max:Draw()
+ self.Text.Title:Draw()
+ self:Functions()
+ end
+end
+
+--[[
+ UIMenu.lua
+ Menus
+--]]
+
+function UIMenu.New(Title, Subtitle, X, Y, TxtDictionary, TxtName, titleTxt)
+ local X, Y = tonumber(X) or 0, tonumber(Y) or 0
+ if Title ~= nil then Title = tostring(Title) or "" else Title = "" end
+ if Subtitle ~= nil then Subtitle = tostring(Subtitle) or "" else Subtitle = "" end
+ if TxtDictionary ~= nil then TxtDictionary = tostring(TxtDictionary) or "commonmenu" else TxtDictionary = "commonmenu" end
+ if TxtName ~= nil then TxtName = tostring(TxtName) or "interaction_bgd" else TxtName = "interaction_bgd" end
+ if titleTxt then
+ thisTitle = Sprite.New(TxtDictionary, titleTxt, 0 + X, 0 + Y, 431, 107)
+ else
+ thisTitle = UIResText.New(Title, 215 + X, 20 + Y, 1.15, 255, 255, 255, 255, 1, 1)
+ end
+ local _UIMenu = {
+ Logo = Sprite.New(TxtDictionary, TxtName, 0 + X, 0 + Y, 431, 107),
+ Banner = nil,
+ Title = thisTitle,
+ Subtitle = {ExtraY = 0},
+ WidthOffset = 0,
+ Position = {X = X, Y = Y},
+ Pagination = {Min = 0, Max = 9, Total = 9},
+ PageCounter = {PreText = ""},
+ Extra = {},
+ Description = {},
+ Items = {},
+ Windows = {},
+ Children = {},
+ TxtDictionary = TxtDictionary,
+ TxtName = TxtName,
+ titleTxt = titleTxt,
+ Controls = {
+ Back = {
+ Enabled = true,
+ },
+ Select = {
+ Enabled = true,
+ },
+ Left = {
+ Enabled = true,
+ },
+ Right = {
+ Enabled = true,
+ },
+ Up = {
+ Enabled = true,
+ },
+ Down = {
+ Enabled = true,
+ },
+ },
+ ParentMenu = nil,
+ ParentItem = nil,
+ _Visible = false,
+ ActiveItem = 1000,
+ Dirty = false;
+ ReDraw = true,
+ InstructionalScaleform = RequestScaleformMovie("INSTRUCTIONAL_BUTTONS"),
+ InstructionalButtons = {},
+ OnIndexChange = function(menu, newindex) end,
+ OnListChange = function(menu, list, newindex) end,
+ OnSliderChange = function(menu, slider, newindex) end,
+ OnProgressChange = function(menu, progress, newindex) end,
+ OnCheckboxChange = function(menu, item, checked) end,
+ OnListSelect = function(menu, list, index) end,
+ OnSliderSelect = function(menu, slider, index) end,
+ OnProgressSelect = function(menu, progress, index) end,
+ OnItemSelect = function(menu, item, index) end,
+ OnMenuChanged = function(menu, newmenu, forward) end,
+ OnMenuClosed = function(menu) end,
+ Settings = {
+ InstructionalButtons = true,
+ MultilineFormats = true,
+ ScaleWithSafezone = true,
+ ResetCursorOnOpen = true,
+ MouseControlsEnabled = true,
+ MouseEdgeEnabled = true,
+ ControlDisablingEnabled = true,
+ Audio = {
+ Library = "HUD_FRONTEND_DEFAULT_SOUNDSET",
+ UpDown = "NAV_UP_DOWN",
+ LeftRight = "NAV_LEFT_RIGHT",
+ Select = "SELECT",
+ Back = "BACK",
+ Error = "ERROR",
+ },
+ EnabledControls = {
+ Controller = {
+ {0, 2}, -- Look Up and Down
+ {0, 1}, -- Look Left and Right
+ {0, 25}, -- Aim
+ {0, 24}, -- Attack
+ },
+ Keyboard = {
+ {0, 201}, -- Select
+ {0, 195}, -- X axis
+ {0, 196}, -- Y axis
+ {0, 187}, -- Down
+ {0, 188}, -- Up
+ {0, 189}, -- Left
+ {0, 190}, -- Right
+ {0, 202}, -- Back
+ {0, 217}, -- Select
+ {0, 242}, -- Scroll down
+ {0, 241}, -- Scroll up
+ {0, 239}, -- Cursor X
+ {0, 240}, -- Cursor Y
+ {0, 31}, -- Move Up and Down
+ {0, 30}, -- Move Left and Right
+ {0, 21}, -- Sprint
+ {0, 22}, -- Jump
+ {0, 23}, -- Enter
+ {0, 75}, -- Exit Vehicle
+ {0, 71}, -- Accelerate Vehicle
+ {0, 72}, -- Vehicle Brake
+ {0, 59}, -- Move Vehicle Left and Right
+ {0, 89}, -- Fly Yaw Left
+ {0, 9}, -- Fly Left and Right
+ {0, 8}, -- Fly Up and Down
+ {0, 90}, -- Fly Yaw Right
+ {0, 76}, -- Vehicle Handbrake
+ },
+ }
+ }
+ }
+
+ if Subtitle ~= "" and Subtitle ~= nil then
+ _UIMenu.Subtitle.Rectangle = UIResRectangle.New(0 + _UIMenu.Position.X, 107 + _UIMenu.Position.Y, 431, 37, 0, 0, 0, 255)
+ _UIMenu.Subtitle.Text = UIResText.New(Subtitle, 8 + _UIMenu.Position.X, 110 + _UIMenu.Position.Y, 0.35, 245, 245, 245, 255, 0)
+ _UIMenu.Subtitle.BackupText = Subtitle
+ _UIMenu.Subtitle.Formatted = false
+ if string.starts(Subtitle, "~") then
+ _UIMenu.PageCounter.PreText = string.sub(Subtitle, 1, 3)
+ end
+ _UIMenu.PageCounter.Text = UIResText.New("", 425 + _UIMenu.Position.X, 110 + _UIMenu.Position.Y, 0.35, 245, 245, 245, 255, 0, "Right")
+ _UIMenu.Subtitle.ExtraY = 37
+ end
+
+ _UIMenu.ArrowSprite = Sprite.New("commonmenu", "shop_arrows_upanddown", 190 + _UIMenu.Position.X, 147 + 37 * (_UIMenu.Pagination.Total + 1) + _UIMenu.Position.Y - 37 + _UIMenu.Subtitle.ExtraY, 50, 50)
+ _UIMenu.Extra.Up = UIResRectangle.New(0 + _UIMenu.Position.X, 144 + 38 * (_UIMenu.Pagination.Total + 1) + _UIMenu.Position.Y - 37 + _UIMenu.Subtitle.ExtraY, 431, 18, 0, 0, 0, 200)
+ _UIMenu.Extra.Down = UIResRectangle.New(0 + _UIMenu.Position.X, 144 + 18 + 38 * (_UIMenu.Pagination.Total + 1) + _UIMenu.Position.Y - 37 + _UIMenu.Subtitle.ExtraY, 431, 18, 0, 0, 0, 200)
+
+ _UIMenu.Description.Bar = UIResRectangle.New(_UIMenu.Position.X, 123, 431, 4, 0, 0, 0, 255)
+ _UIMenu.Description.Rectangle = Sprite.New("commonmenu", "gradient_bgd", _UIMenu.Position.X, 127, 431, 30)
+ _UIMenu.Description.Text = UIResText.New("Description", _UIMenu.Position.X + 5, 125, 0.35)
+
+ _UIMenu.Background = Sprite.New("commonmenu", "gradient_bgd", _UIMenu.Position.X, 144 + _UIMenu.Position.Y - 37 + _UIMenu.Subtitle.ExtraY, 290, 25)
+
+ Citizen.CreateThread(function()
+ if not HasScaleformMovieLoaded(_UIMenu.InstructionalScaleform) then
+ _UIMenu.InstructionalScaleform = RequestScaleformMovie("INSTRUCTIONAL_BUTTONS")
+ while not HasScaleformMovieLoaded(_UIMenu.InstructionalScaleform) do
+ Citizen.Wait(0)
+ end
+ end
+ end)
+ return setmetatable(_UIMenu, UIMenu)
+end
+
+function UIMenu:SetMenuWidthOffset(Offset)
+ if tonumber(Offset) then
+ self.WidthOffset = math.floor(tonumber(Offset))
+ self.Logo:Size(431 + self.WidthOffset, 107)
+ if self.Title.TxtName then
+ self.Title:Position(((self.WidthOffset + 0)/2) + self.Position.X, 0 + self.Position.Y)
+ else
+ self.Title:Position(((self.WidthOffset + 431)/2) + self.Position.X, 20 + self.Position.Y)
+ end
+ if self.Subtitle.Rectangle ~= nil then
+ self.Subtitle.Rectangle:Size(431 + self.WidthOffset + 100, 37)
+ self.PageCounter.Text:Position(425 + self.Position.X + self.WidthOffset, 110 + self.Position.Y)
+ end
+ if self.Banner ~= nil then
+ self.Banner:Size(431 + self.WidthOffset, 107)
+ end
+ end
+end
+
+function UIMenu:DisEnableControls(bool)
+ if bool then
+ EnableAllControlActions(2)
+ else
+ DisableAllControlActions(2)
+ end
+
+ if bool then
+ return
+ else
+ if Controller() then
+ for Index = 1, #self.Settings.EnabledControls.Controller do
+ EnableControlAction(self.Settings.EnabledControls.Controller[Index][1], self.Settings.EnabledControls.Controller[Index][2], true)
+ end
+ else
+ for Index = 1, #self.Settings.EnabledControls.Keyboard do
+ EnableControlAction(self.Settings.EnabledControls.Keyboard[Index][1], self.Settings.EnabledControls.Keyboard[Index][2], true)
+ end
+ end
+ end
+end
+
+function UIMenu:InstructionalButtons(bool)
+ if bool ~= nil then
+ self.Settings.InstrucitonalButtons = tobool(bool)
+ end
+end
+
+function UIMenu:SetBannerSprite(Sprite, IncludeChildren)
+ if Sprite() == "Sprite" then
+ self.Logo = Sprite
+ self.Logo:Size(431 + self.WidthOffset, 107)
+ self.Logo:Position(self.Position.X, self.Position.Y)
+ self.Banner = nil
+ if IncludeChildren then
+ for Item, Menu in pairs(self.Children) do
+ Menu.Logo = Sprite
+ Menu.Logo:Size(431 + self.WidthOffset, 107)
+ Menu.Logo:Position(self.Position.X, self.Position.Y)
+ Menu.Banner = nil
+ end
+ end
+ end
+end
+
+function UIMenu:SetBannerRectangle(Rectangle, IncludeChildren)
+ if Rectangle() == "Rectangle" then
+ self.Banner = Rectangle
+ self.Banner:Size(431 + self.WidthOffset, 107)
+ self.Banner:Position(self.Position.X, self.Position.Y)
+ self.Logo = nil
+ if IncludeChildren then
+ for Item, Menu in pairs(self.Children) do
+ Menu.Banner = Rectangle
+ Menu.Banner:Size(431 + self.WidthOffset, 107)
+ Menu:Position(self.Position.X, self.Position.Y)
+ Menu.Logo = nil
+ end
+ end
+ end
+end
+
+function UIMenu:CurrentSelection(value)
+ if tonumber(value) then
+ if #self.Items == 0 then
+ self.ActiveItem = 0
+ end
+
+ self.Items[self:CurrentSelection()]:Selected(false)
+ self.ActiveItem = 1000000 - (1000000 % #self.Items) + tonumber(value)
+
+ if self:CurrentSelection() > self.Pagination.Max then
+ self.Pagination.Min = self:CurrentSelection() - self.Pagination.Total
+ self.Pagination.Max = self:CurrentSelection()
+ elseif self:CurrentSelection() < self.Pagination.Min then
+ self.Pagination.Min = self:CurrentSelection()
+ self.Pagination.Max = self:CurrentSelection() + self.Pagination.Total
+ end
+ else
+ if #self.Items == 0 then
+ return 1
+ else
+ if self.ActiveItem % #self.Items == 0 then
+ return 1
+ else
+ return self.ActiveItem % #self.Items + 1
+ end
+ end
+ end
+end
+
+function UIMenu:CalculateWindowHeight()
+ local Height = 0
+ for i = 1, #self.Windows do
+ Height = Height + self.Windows[i].Background:Size().Height
+ end
+ return Height
+end
+
+function UIMenu:CalculateItemHeightOffset(Item)
+ if Item.Base then
+ return Item.Base.Rectangle.Height
+ else
+ return Item.Rectangle.Height
+ end
+end
+
+function UIMenu:CalculateItemHeight()
+ local ItemOffset = 0 + self.Subtitle.ExtraY - 37
+ for i = self.Pagination.Min + 1, self.Pagination.Max do
+ local Item = self.Items[i]
+ if Item ~= nil then
+ ItemOffset = ItemOffset + self:CalculateItemHeightOffset(Item)
+ end
+ end
+ return ItemOffset
+end
+
+function UIMenu:RecalculateDescriptionPosition()
+ local WindowHeight = self:CalculateWindowHeight()
+ self.Description.Bar:Position(self.Position.X, 149 + self.Position.Y + WindowHeight)
+ self.Description.Rectangle:Position(self.Position.X, 149 + self.Position.Y + WindowHeight)
+ self.Description.Text:Position(self.Position.X + 8, 155 + self.Position.Y + WindowHeight)
+
+ self.Description.Bar:Size(431 + self.WidthOffset, 4)
+ self.Description.Rectangle:Size(431 + self.WidthOffset, 30)
+
+ self.Description.Bar:Position(self.Position.X, self:CalculateItemHeight() + ((#self.Items > (self.Pagination.Total + 1)) and 37 or 0) + self.Description.Bar:Position().Y)
+ self.Description.Rectangle:Position(self.Position.X, self:CalculateItemHeight() + ((#self.Items > (self.Pagination.Total + 1)) and 37 or 0) + self.Description.Rectangle:Position().Y)
+ self.Description.Text:Position(self.Position.X + 8, self:CalculateItemHeight() + ((#self.Items > (self.Pagination.Total + 1)) and 37 or 0) + self.Description.Text:Position().Y)
+end
+
+function UIMenu:CaclulatePanelPosition(HasDescription)
+ local Height = self:CalculateWindowHeight() + 149 + self.Position.Y
+
+ if HasDescription then
+ Height = Height + self.Description.Rectangle:Size().Height + 5
+ end
+
+ return self:CalculateItemHeight() + ((#self.Items > (self.Pagination.Total + 1)) and 37 or 0) + Height
+end
+
+function UIMenu:AddWindow(Window)
+ if Window() == "UIMenuWindow" then
+ Window:SetParentMenu(self)
+ Window:Offset(self.Position.X, self.Position.Y)
+ table.insert(self.Windows, Window)
+ self.ReDraw = true
+ self:RecalculateDescriptionPosition()
+ end
+end
+
+function UIMenu:RemoveWindowAt(Index)
+ if tonumber(Index) then
+ if self.Windows[Index] then
+ table.remove(self.Windows, Index)
+ self.ReDraw = true
+ self:RecalculateDescriptionPosition()
+ end
+ end
+end
+
+function UIMenu:AddItem(Item)
+ if Item() == "UIMenuItem" then
+ local SelectedItem = self:CurrentSelection()
+ Item:SetParentMenu(self)
+ Item:Offset(self.Position.X, self.Position.Y)
+ Item:Position((#self.Items * 25) - 37 + self.Subtitle.ExtraY)
+ table.insert(self.Items, Item)
+ self:RecalculateDescriptionPosition()
+ self:CurrentSelection(SelectedItem)
+ end
+end
+
+function UIMenu:RemoveItemAt(Index)
+ if tonumber(Index) then
+ if self.Items[Index] then
+ local SelectedItem = self:CurrentSelection()
+ if #self.Items > self.Pagination.Total and self.Pagination.Max == #self.Items - 1 then
+ self.Pagination.Min = self.Pagination.Min - 1
+ self.Pagination.Max = self.Pagination.Max + 1
+ end
+ table.remove(self.Items, tonumber(Index))
+ self:RecalculateDescriptionPosition()
+ self:CurrentSelection(SelectedItem)
+ end
+ end
+end
+
+function UIMenu:RefreshIndex()
+ if #self.Items == 0 then
+ self.ActiveItem = 1000
+ self.Pagination.Max = self.Pagination.Total + 1
+ self.Pagination.Min = 0
+ return
+ end
+ self.Items[self:CurrentSelection()]:Selected(false)
+ self.ActiveItem = 1000 - (1000 % #self.Items)
+ self.Pagination.Max = self.Pagination.Total + 1
+ self.Pagination.Min = 0
+ self.ReDraw = true
+end
+
+function UIMenu:Clear()
+ self.Items = {}
+ self.ReDraw = true
+ self:RecalculateDescriptionPosition()
+end
+
+function UIMenu:MultilineFormat(str)
+ if tostring(str) then
+
+ local PixelPerLine = 425 + self.WidthOffset
+ local AggregatePixels = 0
+ local output = ""
+ local words = string.split(tostring(str), " ")
+
+ for i = 1, #words do
+ local offset = MeasureStringWidth(words[i], 0, 0.35)
+ AggregatePixels = AggregatePixels + offset
+ if AggregatePixels > PixelPerLine then
+ output = output .. "\n" .. words[i] .. " "
+ AggregatePixels = offset + MeasureString(" ")
+ else
+ output = output .. words[i] .. " "
+ AggregatePixels = AggregatePixels + MeasureString(" ")
+ end
+ end
+ return output
+ end
+end
+
+function UIMenu:DrawCalculations()
+ local WindowHeight = self:CalculateWindowHeight()
+
+ if self.Settings.MultilineFormats then
+ if self.Subtitle.Rectangle and not self.Subtitle.Formatted then
+ self.Subtitle.Formatted = true
+ self.Subtitle.Text:Text(self:MultilineFormat(self.Subtitle.Text:Text()))
+
+ local Linecount = #string.split(self.Subtitle.Text:Text(), "\n")
+ self.Subtitle.ExtraY = ((Linecount == 1) and 37 or ((Linecount + 1) * 22))
+ self.Subtitle.Rectangle:Size(431 + self.WidthOffset, self.Subtitle.ExtraY)
+ end
+ elseif self.Subtitle.Formatted then
+ self.Subtitle.Formatted = false
+ self.Subtitle.ExtraY = 37
+ self.Subtitle.Rectangle:Size(431 + self.WidthOffset, self.Subtitle.ExtraY)
+ self.Subtitle.Text:Text(self.Subtitle.BackupText)
+ end
+
+ self.Background:Size(431 + self.WidthOffset, self:CalculateItemHeight() + WindowHeight + ((self.Subtitle.ExtraY > 0) and 0 or 37))
+
+ self.Extra.Up:Size(431 + self.WidthOffset, 18)
+ self.Extra.Down:Size(431 + self.WidthOffset, 18)
+
+ self.Extra.Up:Position(self.Position.X, 144 + self:CalculateItemHeight() + self.Position.Y + WindowHeight)
+ self.Extra.Down:Position(self.Position.X, 144 + 18 + self:CalculateItemHeight() + self.Position.Y + WindowHeight)
+
+ if self.WidthOffset > 0 then
+ self.ArrowSprite:Position(190 + self.Position.X + (self.WidthOffset / 2), 137 + self:CalculateItemHeight() + self.Position.Y + WindowHeight)
+ else
+ self.ArrowSprite:Position(190 + self.Position.X + self.WidthOffset, 137 + self:CalculateItemHeight() + self.Position.Y + WindowHeight)
+ end
+
+ self.ReDraw = false
+
+ if #self.Items ~= 0 and self.Items[self:CurrentSelection()]:Description() ~= "" then
+ self:RecalculateDescriptionPosition()
+
+ local description = self.Items[self:CurrentSelection()]:Description()
+ if self.Settings.MultilineFormats then
+ self.Description.Text:Text(self:MultilineFormat(description))
+ else
+ self.Description.Text:Text(description)
+ end
+
+ local Linecount = #string.split(self.Description.Text:Text(), "\n")
+ self.Description.Rectangle:Size(431 + self.WidthOffset, ((Linecount == 1) and 37 or ((Linecount + 1) * 22)))
+ end
+end
+
+function UIMenu:Visible(bool)
+ if bool ~= nil then
+ menuOpen = bool
+ self._Visible = tobool(bool)
+ self.JustOpened = tobool(bool)
+ self.Dirty = tobool(bool)
+ self:UpdateScaleform()
+ if self.ParentMenu ~= nil or tobool(bool) == false then
+ return
+ end
+ if self.Settings.ResetCursorOnOpen then
+ local W, H = GetScreenResolution()
+ SetCursorLocation(W / 2, H / 2)
+ SetCursorSprite(1)
+ end
+ collectgarbage()
+ else
+ return self._Visible
+ end
+end
+
+function UIMenu:ProcessControl()
+ if not self._Visible then
+ return
+ end
+
+ if self.JustOpened then
+ self.JustOpened = false
+ return
+ end
+
+ if self.Controls.Back.Enabled and (IsDisabledControlJustReleased(2, 177) or IsDisabledControlJustReleased(2, 199) ) and IsInputDisabled(0) then
+ self:GoBack()
+ end
+
+ if #self.Items == 0 then
+ return
+ end
+
+ if not self.UpPressed then
+ if self.Controls.Up.Enabled and (IsDisabledControlJustPressed(1, 172) or IsDisabledControlJustPressed(1, 241)) and IsInputDisabled(0) then
+ Citizen.CreateThread(function()
+ self.UpPressed = true
+ if #self.Items > self.Pagination.Total + 1 then
+ self:GoUpOverflow()
+ else
+ self:GoUp()
+ end
+ self:UpdateScaleform()
+ Citizen.Wait(175)
+ while self.Controls.Up.Enabled and (IsDisabledControlPressed(2, 172) or IsDisabledControlPressed(2, 241)) and IsInputDisabled(0) do
+ if #self.Items > self.Pagination.Total + 1 then
+ self:GoUpOverflow()
+ else
+ self:GoUp()
+ end
+ self:UpdateScaleform()
+ Citizen.Wait(125)
+ end
+ self.UpPressed = false
+ end)
+ end
+ end
+
+ if not self.DownPressed then
+ if self.Controls.Down.Enabled and (IsDisabledControlJustPressed(1, 173) or IsDisabledControlJustPressed(1, 242)) and IsInputDisabled(0) then
+ Citizen.CreateThread(function()
+ self.DownPressed = true
+ if #self.Items > self.Pagination.Total + 1 then
+ self:GoDownOverflow()
+ else
+ self:GoDown()
+ end
+ self:UpdateScaleform()
+ Citizen.Wait(175)
+ while self.Controls.Down.Enabled and (IsDisabledControlPressed(2, 173) or IsDisabledControlPressed(2, 242)) and IsInputDisabled(0) do
+ if #self.Items > self.Pagination.Total + 1 then
+ self:GoDownOverflow()
+ else
+ self:GoDown()
+ end
+ self:UpdateScaleform()
+ Citizen.Wait(125)
+ end
+ self.DownPressed = false
+ end)
+ end
+ end
+
+ if not self.LeftPressed then
+ if self.Controls.Left.Enabled and (IsDisabledControlPressed(2, 174)) and IsInputDisabled(0) then
+ Citizen.CreateThread(function()
+ if not self.LeftPressed then
+ self.LeftPressed = true
+ self:GoLeft()
+ Citizen.Wait(150)
+ while self.Controls.Left.Enabled and (IsDisabledControlPressed(2, 174)) and IsInputDisabled(0) do
+ self:GoLeft()
+ Citizen.Wait(200)
+ end
+ self.LeftPressed = false
+ end
+ end)
+ end
+ end
+
+ if not self.RightPressed then
+ if self.Controls.Right.Enabled and (IsDisabledControlPressed(2, 175)) and IsInputDisabled(0) then
+ Citizen.CreateThread(function()
+ if not self.RightPressed then
+ self.RightPressed = true
+ self:GoRight()
+ Citizen.Wait(150)
+ while self.Controls.Right.Enabled and (IsDisabledControlPressed(2, 175)) and IsInputDisabled(0) do
+ self:GoRight()
+ Citizen.Wait(200)
+ end
+ self.RightPressed = false
+ end
+ end)
+ end
+ end
+
+ if self.Controls.Select.Enabled and (IsDisabledControlJustPressed(1, 201) and IsInputDisabled(0)) then
+ self:SelectItem()
+ end
+end
+
+function UIMenu:GoUpOverflow()
+ if #self.Items <= self.Pagination.Total + 1 then
+ return
+ end
+
+ if self:CurrentSelection() <= self.Pagination.Min + 1 then
+ if self:CurrentSelection() == 1 then
+ self.Pagination.Min = #self.Items - (self.Pagination.Total + 1)
+ self.Pagination.Max = #self.Items
+ self.Items[self:CurrentSelection()]:Selected(false)
+ self.ActiveItem = 1000 - (1000 % #self.Items)
+ self.ActiveItem = self.ActiveItem + (#self.Items - 1)
+ self.Items[self:CurrentSelection()]:Selected(true)
+ else
+ self.Pagination.Min = self.Pagination.Min - 1
+ self.Pagination.Max = self.Pagination.Max - 1
+ self.Items[self:CurrentSelection()]:Selected(false)
+ self.ActiveItem = self.ActiveItem - 1
+ self.Items[self:CurrentSelection()]:Selected(true)
+ end
+ else
+ self.Items[self:CurrentSelection()]:Selected(false)
+ self.ActiveItem = self.ActiveItem - 1
+ self.Items[self:CurrentSelection()]:Selected(true)
+ end
+ PlaySoundFrontend(-1, self.Settings.Audio.UpDown, self.Settings.Audio.Library, true)
+ self.OnIndexChange(self, self:CurrentSelection())
+ self.ReDraw = true
+end
+
+function UIMenu:GoUp()
+ if #self.Items > self.Pagination.Total + 1 then
+ return
+ end
+ self.Items[self:CurrentSelection()]:Selected(false)
+ self.ActiveItem = self.ActiveItem - 1
+ self.Items[self:CurrentSelection()]:Selected(true)
+ PlaySoundFrontend(-1, self.Settings.Audio.UpDown, self.Settings.Audio.Library, true)
+ self.OnIndexChange(self, self:CurrentSelection())
+ self.ReDraw = true
+end
+
+function UIMenu:GoDownOverflow()
+ if #self.Items <= self.Pagination.Total + 1 then
+ return
+ end
+
+ if self:CurrentSelection() >= self.Pagination.Max then
+ if self:CurrentSelection() == #self.Items then
+ self.Pagination.Min = 0
+ self.Pagination.Max = self.Pagination.Total + 1
+ self.Items[self:CurrentSelection()]:Selected(false)
+ self.ActiveItem = 1000 - (1000 % #self.Items)
+ self.Items[self:CurrentSelection()]:Selected(true)
+ else
+ self.Pagination.Max = self.Pagination.Max + 1
+ self.Pagination.Min = self.Pagination.Max - (self.Pagination.Total + 1)
+ self.Items[self:CurrentSelection()]:Selected(false)
+ self.ActiveItem = self.ActiveItem + 1
+ self.Items[self:CurrentSelection()]:Selected(true)
+ end
+ else
+ self.Items[self:CurrentSelection()]:Selected(false)
+ self.ActiveItem = self.ActiveItem + 1
+ self.Items[self:CurrentSelection()]:Selected(true)
+ end
+ PlaySoundFrontend(-1, self.Settings.Audio.UpDown, self.Settings.Audio.Library, true)
+ self.OnIndexChange(self, self:CurrentSelection())
+ self.ReDraw = true
+end
+
+function UIMenu:GoDown()
+ if #self.Items > self.Pagination.Total + 1 then
+ return
+ end
+
+ self.Items[self:CurrentSelection()]:Selected(false)
+ self.ActiveItem = self.ActiveItem + 1
+ self.Items[self:CurrentSelection()]:Selected(true)
+ PlaySoundFrontend(-1, self.Settings.Audio.UpDown, self.Settings.Audio.Library, true)
+ self.OnIndexChange(self, self:CurrentSelection())
+ self.ReDraw = true
+end
+
+function UIMenu:GoLeft()
+ local type, subtype = self.Items[self:CurrentSelection()]()
+ if subtype ~= "UIMenuListItem" and subtype ~= "UIMenuSliderItem" and subtype ~= "UIMenuProgressItem" then
+ return
+ end
+
+ if not self.Items[self:CurrentSelection()]:Enabled() then
+ PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true)
+ return
+ end
+
+ if subtype == "UIMenuListItem" then
+ local Item = self.Items[self:CurrentSelection()]
+ Item:Index(Item._Index - 1)
+ self.OnListChange(self, Item, Item._Index)
+ Item.OnListChanged(self, Item, Item._Index)
+ PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true)
+ elseif subtype == "UIMenuSliderItem" then
+ local Item = self.Items[self:CurrentSelection()]
+ Item:Index(Item._Index - 1)
+ self.OnSliderChange(self, Item, Item:Index())
+ Item.OnSliderChanged(self, Item, Item._Index)
+ PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true)
+ elseif subtype == "UIMenuProgressItem" then
+ local Item = self.Items[self:CurrentSelection()]
+ Item:Index(Item.Data.Index - 1)
+ self.OnProgressChange(self, Item, Item.Data.Index)
+ Item.OnProgressChanged(self, Item, Item.Data.Index)
+ PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true)
+ end
+end
+
+function UIMenu:GoRight()
+ local type, subtype = self.Items[self:CurrentSelection()]()
+ if subtype ~= "UIMenuListItem" and subtype ~= "UIMenuSliderItem" and subtype ~= "UIMenuProgressItem" then
+ return
+ end
+
+ if not self.Items[self:CurrentSelection()]:Enabled() then
+ PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true)
+ return
+ end
+
+ if subtype == "UIMenuListItem" then
+ local Item = self.Items[self:CurrentSelection()]
+ Item:Index(Item._Index + 1)
+ self.OnListChange(self, Item, Item._Index)
+ Item.OnListChanged(self, Item, Item._Index)
+ PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true)
+ elseif subtype == "UIMenuSliderItem" then
+ local Item = self.Items[self:CurrentSelection()]
+ Item:Index(Item._Index + 1)
+ self.OnSliderChange(self, Item, Item:Index())
+ Item.OnSliderChanged(self, Item, Item._Index)
+ PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true)
+ elseif subtype == "UIMenuProgressItem" then
+ local Item = self.Items[self:CurrentSelection()]
+ Item:Index(Item.Data.Index + 1)
+ self.OnProgressChange(self, Item, Item.Data.Index)
+ Item.OnProgressChanged(self, Item, Item.Data.Index)
+ PlaySoundFrontend(-1, self.Settings.Audio.LeftRight, self.Settings.Audio.Library, true)
+ end
+end
+
+function UIMenu:SelectItem()
+ if not self.Items[self:CurrentSelection()]:Enabled() then
+ PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true)
+ return
+ end
+ local Item = self.Items[self:CurrentSelection()]
+ local type, subtype = Item()
+ if subtype == "UIMenuCheckboxItem" then
+ Item.Checked = not Item.Checked
+ PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true)
+ self.OnCheckboxChange(self, Item, Item.Checked)
+ Item.CheckboxEvent(self, Item, Item.Checked)
+ elseif subtype == "UIMenuListItem" then
+ PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true)
+ self.OnListSelect(self, Item, Item._Index)
+ Item.OnListSelected(self, Item, Item._Index)
+ elseif subtype == "UIMenuSliderItem" then
+ PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true)
+ self.OnSliderSelect(self, Item, Item._Index)
+ Item.OnSliderSelected(Item._Index)
+ elseif subtype == "UIMenuProgressItem" then
+ PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true)
+ self.OnProgressSelect(self, Item, Item.Data.Index)
+ Item.OnProgressSelected(Item.Data.Index)
+ else
+ PlaySoundFrontend(-1, self.Settings.Audio.Select, self.Settings.Audio.Library, true)
+ self.OnItemSelect(self, Item, self:CurrentSelection())
+ Item.Activated(self, Item)
+ if not self.Children[Item] then
+ return
+ end
+ self:Visible(false)
+ self.Children[Item]:Visible(true)
+ self.OnMenuChanged(self, self.Children[self.Items[self:CurrentSelection()]], true)
+ end
+end
+
+function UIMenu:GoBack()
+ PlaySoundFrontend(-1, self.Settings.Audio.Back, self.Settings.Audio.Library, true)
+ self:Visible(false)
+ if self.ParentMenu ~= nil then
+ self.ParentMenu:Visible(true)
+ self.OnMenuChanged(self, self.ParentMenu, false)
+ if self.Settings.ResetCursorOnOpen then
+ local W, H = GetActiveScreenResolution()
+ SetCursorLocation(W / 2, H / 2)
+ end
+ end
+ self.OnMenuClosed(self)
+end
+
+function UIMenu:BindMenuToItem(Menu, Item)
+ if Menu() == "UIMenu" and Item() == "UIMenuItem" then
+ Menu.ParentMenu = self
+ Menu.ParentItem = Item
+ self.Children[Item] = Menu
+ end
+end
+
+function UIMenu:ReleaseMenuFromItem(Item)
+ if Item() == "UIMenuItem" then
+ if not self.Children[Item] then
+ return false
+ end
+ self.Children[Item].ParentMenu = nil
+ self.Children[Item].ParentItem = nil
+ self.Children[Item] = nil
+ return true
+ end
+end
+
+function UIMenu:Draw()
+ if not self._Visible then
+ return
+ end
+
+ HideHudComponentThisFrame(19)
+
+ if self.Settings.ControlDisablingEnabled then
+ self:DisEnableControls(false)
+ end
+
+ if self.Settings.InstructionalButtons then
+ DrawScaleformMovieFullscreen(self.InstructionalScaleform, 255, 255, 255, 255, 0)
+ end
+
+ if self.Settings.ScaleWithSafezone then
+ ScreenDrawPositionBegin(76, 84)
+ ScreenDrawPositionRatio(0, 0, 0, 0)
+ end
+
+ if self.ReDraw then
+ self:DrawCalculations()
+ end
+
+ if self.Logo then
+ self.Logo:Draw()
+ elseif self.Banner then
+ self.Banner:Draw()
+ end
+
+ self.Title:Draw()
+
+ if self.Subtitle.Rectangle then
+ self.Subtitle.Rectangle:Draw()
+ self.Subtitle.Text:Draw()
+ end
+
+ if #self.Items ~= 0 or #self.Windows ~= 0 then
+ self.Background:Draw()
+ end
+
+ if #self.Windows ~= 0 then
+ local WindowOffset = 0
+ for index = 1, #self.Windows do
+ if self.Windows[index - 1] then
+ WindowOffset = WindowOffset + self.Windows[index - 1].Background:Size().Height
+ end
+ local Window = self.Windows[index]
+ Window:Position(WindowOffset + self.Subtitle.ExtraY - 37)
+ Window:Draw()
+ end
+ end
+
+ if #self.Items == 0 then
+ if self.Settings.ScaleWithSafezone then
+ ScreenDrawPositionEnd()
+ end
+ return
+ end
+
+ local CurrentSelection = self:CurrentSelection()
+ self.Items[CurrentSelection]:Selected(true)
+
+ if self.Items[CurrentSelection]:Description() ~= "" then
+ self.Description.Bar:Draw()
+ self.Description.Rectangle:Draw()
+ self.Description.Text:Draw()
+ end
+
+ if self.Items[CurrentSelection].Panels ~= nil then
+ if #self.Items[CurrentSelection].Panels ~= 0 then
+ local PanelOffset = self:CaclulatePanelPosition(self.Items[CurrentSelection]:Description() ~= "")
+ for index = 1, #self.Items[CurrentSelection].Panels do
+ if self.Items[CurrentSelection].Panels[index - 1] then
+ PanelOffset = PanelOffset + self.Items[CurrentSelection].Panels[index - 1].Background:Size().Height + 5
+ end
+ self.Items[CurrentSelection].Panels[index]:Position(PanelOffset)
+ self.Items[CurrentSelection].Panels[index]:Draw()
+ end
+ end
+ end
+
+ local WindowHeight = self:CalculateWindowHeight()
+
+ if #self.Items <= self.Pagination.Total + 1 then
+ local ItemOffset = self.Subtitle.ExtraY - 37 + WindowHeight
+ for index = 1, #self.Items do
+ Item = self.Items[index]
+ Item:Position(ItemOffset)
+ Item:Draw()
+ ItemOffset = ItemOffset + self:CalculateItemHeightOffset(Item)
+ end
+ else
+ local ItemOffset = self.Subtitle.ExtraY - 37 + WindowHeight
+ for index = self.Pagination.Min + 1, self.Pagination.Max, 1 do
+ if self.Items[index] then
+ Item = self.Items[index]
+ Item:Position(ItemOffset)
+ Item:Draw()
+ ItemOffset = ItemOffset + self:CalculateItemHeightOffset(Item)
+ end
+ end
+
+ self.Extra.Up:Draw()
+ self.Extra.Down:Draw()
+ self.ArrowSprite:Draw()
+
+ if self.PageCounter.Text ~= nil then
+ local Caption = self.PageCounter.PreText .. CurrentSelection .. " / " .. #self.Items
+ self.PageCounter.Text:Text(Caption)
+ self.PageCounter.Text:Draw()
+ end
+ end
+
+ if self.Settings.ScaleWithSafezone then
+ ScreenDrawPositionEnd()
+ end
+end
+
+function UIMenu:ProcessMouse()
+ if not self._Visible or self.JustOpened or #self.Items == 0 or tobool(Controller()) or not self.Settings.MouseControlsEnabled then
+ EnableControlAction(0, 2, true)
+ EnableControlAction(0, 1, true)
+ EnableControlAction(0, 25, true)
+ EnableControlAction(0, 24, true)
+ if self.Dirty then
+ for _, Item in pairs(self.Items) do
+ if Item:Hovered() then
+ Item:Hovered(false)
+ end
+ end
+ end
+ return
+ end
+
+ local SafeZone = {X = 0, Y = 0}
+ local WindowHeight = self:CalculateWindowHeight()
+ if self.Settings.ScaleWithSafezone then
+ SafeZone = GetSafeZoneBounds()
+ end
+
+ local Limit = #self.Items
+ local ItemOffset = 0
+
+ ShowCursorThisFrame()
+
+ if #self.Items > self.Pagination.Total + 1 then
+ Limit = self.Pagination.Max
+ end
+
+ if IsMouseInBounds(0, 0, 30, 1080) and self.Settings.MouseEdgeEnabled then
+ SetGameplayCamRelativeHeading(GetGameplayCamRelativeHeading() + 5)
+ SetCursorSprite(6)
+ elseif IsMouseInBounds(1920 - 30, 0, 30, 1080) and self.Settings.MouseEdgeEnabled then
+ SetGameplayCamRelativeHeading(GetGameplayCamRelativeHeading() - 5)
+ SetCursorSprite(7)
+ elseif self.Settings.MouseEdgeEnabled then
+ SetCursorSprite(1)
+ end
+
+ for i = self.Pagination.Min + 1, Limit, 1 do
+ local X, Y = self.Position.X + SafeZone.X, self.Position.Y + 144 - 37 + self.Subtitle.ExtraY + ItemOffset + SafeZone.Y + WindowHeight
+ local Item = self.Items[i]
+ local Type, SubType = Item()
+ local Width, Height = 431 + self.WidthOffset, self:CalculateItemHeightOffset(Item)
+
+ if IsMouseInBounds(X, Y, Width, Height) then
+ Item:Hovered(true)
+ if not self.Controls.MousePressed then
+ if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then
+ Citizen.CreateThread(function()
+ local _X, _Y, _Width, _Height = X, Y, Width, Height
+ self.Controls.MousePressed = true
+ if Item:Selected() and Item:Enabled() then
+ if SubType == "UIMenuListItem" then
+ if IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then
+ self:GoLeft()
+ elseif not IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then
+ self:SelectItem()
+ end
+ if IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then
+ self:GoRight()
+ elseif not IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then
+ self:SelectItem()
+ end
+ elseif SubType == "UIMenuSliderItem" then
+ if IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then
+ self:GoLeft()
+ elseif not IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then
+ self:SelectItem()
+ end
+ if IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then
+ self:GoRight()
+ elseif not IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then
+ self:SelectItem()
+ end
+ elseif SubType == "UIMenuProgressItem" then
+ if IsMouseInBounds(Item.Bar.X + SafeZone.X, Item.Bar.Y + SafeZone.Y - 12, Item.Data.Max, Item.Bar.Height + 24) then
+ Item:CalculateProgress(math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X)
+ self.OnProgressChange(self, Item, Item.Data.Index)
+ Item.OnProgressChanged(self, Item, Item.Data.Index)
+ else
+ self:SelectItem()
+ end
+ else
+ self:SelectItem()
+ end
+ elseif not Item:Selected() then
+ self:CurrentSelection(i-1)
+ PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true)
+ self.OnIndexChange(self, self:CurrentSelection())
+ self.ReDraw = true
+ self:UpdateScaleform()
+ elseif not Item:Enabled() and Item:Selected() then
+ PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true)
+ end
+ Citizen.Wait(175)
+ while IsDisabledControlPressed(0, 24) and IsMouseInBounds(_X, _Y, _Width, _Height) do
+ if Item:Selected() and Item:Enabled() then
+ if SubType == "UIMenuListItem" then
+ if IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then
+ self:GoLeft()
+ end
+ if IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then
+ self:GoRight()
+ end
+ elseif SubType == "UIMenuSliderItem" then
+ if IsMouseInBounds(Item.LeftArrow.X + SafeZone.X, Item.LeftArrow.Y + SafeZone.Y, Item.LeftArrow.Width, Item.LeftArrow.Height) then
+ self:GoLeft()
+ end
+ if IsMouseInBounds(Item.RightArrow.X + SafeZone.X, Item.RightArrow.Y + SafeZone.Y, Item.RightArrow.Width, Item.RightArrow.Height) then
+ self:GoRight()
+ end
+ elseif SubType == "UIMenuProgressItem" then
+ if IsMouseInBounds(Item.Bar.X + SafeZone.X, Item.Bar.Y + SafeZone.Y - 12, Item.Data.Max, Item.Bar.Height + 24) then
+ Item:CalculateProgress(math.round(GetControlNormal(0, 239) * 1920) - SafeZone.X)
+ self.OnProgressChange(self, Item, Item.Data.Index)
+ Item.OnProgressChanged(self, Item, Item.Data.Index)
+ else
+ self:SelectItem()
+ end
+ end
+ elseif not Item:Selected() then
+ self:CurrentSelection(i-1)
+ PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true)
+ self.OnIndexChange(self, self:CurrentSelection())
+ self.ReDraw = true
+ self:UpdateScaleform()
+ elseif not Item:Enabled() and Item:Selected() then
+ PlaySoundFrontend(-1, self.Settings.Audio.Error, self.Settings.Audio.Library, true)
+ end
+ Citizen.Wait(125)
+ end
+ self.Controls.MousePressed = false
+ end)
+ end
+ end
+ else
+ Item:Hovered(false)
+ end
+ ItemOffset = ItemOffset + self:CalculateItemHeightOffset(Item)
+ end
+
+ local ExtraX, ExtraY = self.Position.X + SafeZone.X, 144 + self:CalculateItemHeight() + self.Position.Y + SafeZone.Y + WindowHeight
+
+ if #self.Items <= self.Pagination.Total + 1 then return end
+
+ if IsMouseInBounds(ExtraX, ExtraY, 431 + self.WidthOffset, 18) then
+ self.Extra.Up:Colour(30, 30, 30, 255)
+ if not self.Controls.MousePressed then
+ if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then
+ Citizen.CreateThread(function()
+ local _ExtraX, _ExtraY = ExtraX, ExtraY
+ self.Controls.MousePressed = true
+ if #self.Items > self.Pagination.Total + 1 then
+ self:GoUpOverflow()
+ else
+ self:GoUp()
+ end
+ Citizen.Wait(175)
+ while IsDisabledControlPressed(0, 24) and IsMouseInBounds(_ExtraX, _ExtraY, 431 + self.WidthOffset, 18) do
+ if #self.Items > self.Pagination.Total + 1 then
+ self:GoUpOverflow()
+ else
+ self:GoUp()
+ end
+ Citizen.Wait(125)
+ end
+ self.Controls.MousePressed = false
+ end)
+ end
+ end
+ else
+ self.Extra.Up:Colour(0, 0, 0, 200)
+ end
+
+ if IsMouseInBounds(ExtraX, ExtraY + 18, 431 + self.WidthOffset, 18) then
+ self.Extra.Down:Colour(30, 30, 30, 255)
+ if not self.Controls.MousePressed then
+ if IsDisabledControlJustPressed(1, 24) and IsInputDisabled(0) then
+ Citizen.CreateThread(function()
+ local _ExtraX, _ExtraY = ExtraX, ExtraY
+ self.Controls.MousePressed = true
+ if #self.Items > self.Pagination.Total + 1 then
+ self:GoDownOverflow()
+ else
+ self:GoDown()
+ end
+ Citizen.Wait(175)
+ while IsDisabledControlPressed(0, 24) and IsMouseInBounds(_ExtraX, _ExtraY + 18, 431 + self.WidthOffset, 18) do
+ if #self.Items > self.Pagination.Total + 1 then
+ self:GoDownOverflow()
+ else
+ self:GoDown()
+ end
+ Citizen.Wait(125)
+ end
+ self.Controls.MousePressed = false
+ end)
+ end
+ end
+ else
+ self.Extra.Down:Colour(0, 0, 0, 200)
+ end
+end
+
+function UIMenu:AddInstructionButton(button)
+ if type(button) == "table" and #button == 2 then
+ table.insert(self.InstructionalButtons, button)
+ end
+end
+
+function UIMenu:RemoveInstructionButton(button)
+ if type(button) == "table" then
+ for i = 1, #self.InstructionalButtons do
+ if button == self.InstructionalButtons[i] then
+ table.remove(self.InstructionalButtons, i)
+ break
+ end
+ end
+ else
+ if tonumber(button) then
+ if self.InstructionalButtons[tonumber(button)] then
+ table.remove(self.InstructionalButtons, tonumber(button))
+ end
+ end
+ end
+end
+
+function UIMenu:AddEnabledControl(Inputgroup, Control, Controller)
+ if tonumber(Inputgroup) and tonumber(Control) then
+ table.insert(self.Settings.EnabledControls[(Controller and "Controller" or "Keyboard")], {Inputgroup, Control})
+ end
+end
+
+function UIMenu:RemoveEnabledControl(Inputgroup, Control, Controller)
+ local Type = (Controller and "Controller" or "Keyboard")
+ for Index = 1, #self.Settings.EnabledControls[Type] do
+ if Inputgroup == self.Settings.EnabledControls[Type][Index][1] and Control == self.Settings.EnabledControls[Type][Index][2] then
+ table.remove(self.Settings.EnabledControls[Type], Index)
+ break
+ end
+ end
+end
+
+function UIMenu:UpdateScaleform()
+ if not self._Visible or not self.Settings.InstructionalButtons then
+ return
+ end
+
+ PushScaleformMovieFunction(self.InstructionalScaleform, "CLEAR_ALL")
+ PopScaleformMovieFunction()
+
+ PushScaleformMovieFunction(self.InstructionalScaleform, "TOGGLE_MOUSE_BUTTONS")
+ PushScaleformMovieFunctionParameterInt(0)
+ PopScaleformMovieFunction()
+
+ PushScaleformMovieFunction(self.InstructionalScaleform, "CREATE_CONTAINER")
+ PopScaleformMovieFunction()
+
+ PushScaleformMovieFunction(self.InstructionalScaleform, "SET_DATA_SLOT")
+ PushScaleformMovieFunctionParameterInt(0)
+ PushScaleformMovieFunctionParameterString(GetControlInstructionalButton(2, 176, 0))
+ PushScaleformMovieFunctionParameterString("Select")
+ PopScaleformMovieFunction()
+
+ if self.Controls.Back.Enabled then
+ PushScaleformMovieFunction(self.InstructionalScaleform, "SET_DATA_SLOT")
+ PushScaleformMovieFunctionParameterInt(1)
+ PushScaleformMovieFunctionParameterString(GetControlInstructionalButton(2, 177, 0))
+ PushScaleformMovieFunctionParameterString("Back")
+ PopScaleformMovieFunction()
+ end
+
+ local count = 2
+
+ for i = 1, #self.InstructionalButtons do
+ if self.InstructionalButtons[i] then
+ if #self.InstructionalButtons[i] == 2 then
+ PushScaleformMovieFunction(self.InstructionalScaleform, "SET_DATA_SLOT")
+ PushScaleformMovieFunctionParameterInt(count)
+ PushScaleformMovieFunctionParameterString(self.InstructionalButtons[i][1])
+ PushScaleformMovieFunctionParameterString(self.InstructionalButtons[i][2])
+ PopScaleformMovieFunction()
+ count = count + 1
+ end
+ end
+ end
+
+ PushScaleformMovieFunction(self.InstructionalScaleform, "DRAW_INSTRUCTIONAL_BUTTONS")
+ PushScaleformMovieFunctionParameterInt(-1)
+ PopScaleformMovieFunction()
+end
+
+--[[
+ MenuPool.lua
+ Menus
+--]]
+
+function MenuPool.New()
+ local _MenuPool = {
+ Menus = {}
+ }
+ return setmetatable(_MenuPool, MenuPool)
+end
+
+function MenuPool:AddSubMenu(Menu, Text, Description, KeepPosition, KeepBanner)
+ if Menu() == "UIMenu" then
+ local Item = UIMenuItem.New(tostring(Text), Description or "")
+ Menu:AddItem(Item)
+ local SubMenu
+
+ if KeepPosition then
+ if Menu.Title.TxtName then
+ SubMenu = UIMenu.New("", Text, Menu.Position.X, Menu.Position.Y, Menu.TxtDictionary, Menu.TxtName, Menu.titleTxt)
+ else
+ SubMenu = UIMenu.New(Menu.Title._Text, Text, Menu.Position.X, Menu.Position.Y, Menu.TxtDictionary, Menu.TxtName)
+ end
+ else
+ if Menu.Title.TxtName then
+ SubMenu = UIMenu.New("", Text, 0, 0, Menu.TxtDictionary, Menu.TxtName, Menu.titleTxt)
+ else
+ SubMenu = UIMenu.New(Menu.Title._Text, Text, 0, 0, Menu.TxtDictionary, Menu.TxtName, Menu.titleTxt)
+ end
+ end
+ if KeepBanner then
+ if Menu.Logo ~= nil then
+ SubMenu.Logo = Menu.Logo
+ else
+ SubMenu.Logo = nil
+ SubMenu.Banner = Menu.Banner
+ end
+ end
+ Item:RightLabel('→→→')
+ self:Add(SubMenu)
+ Menu:BindMenuToItem(SubMenu, Item)
+ return SubMenu
+ end
+end
+
+function MenuPool:Add(Menu)
+ if Menu() == "UIMenu" then
+ table.insert(self.Menus, Menu)
+ end
+end
+
+function MenuPool:Clear()
+ self = {
+ Menus = {}
+ }
+ collectgarbage()
+end
+
+function MenuPool:Remove()
+ self = nil
+ collectgarbage()
+end
+
+function MenuPool:MouseEdgeEnabled(bool)
+ if bool ~= nil then
+ for _, Menu in pairs(self.Menus) do
+ Menu.Settings.MouseEdgeEnabled = tobool(bool)
+ end
+ end
+end
+
+function MenuPool:ControlDisablingEnabled(bool)
+ if bool ~= nil then
+ for _, Menu in pairs(self.Menus) do
+ Menu.Settings.ControlDisablingEnabled = tobool(bool)
+ end
+ end
+end
+
+function MenuPool:ResetCursorOnOpen(bool)
+ if bool ~= nil then
+ for _, Menu in pairs(self.Menus) do
+ Menu.Settings.ResetCursorOnOpen = tobool(bool)
+ end
+ end
+end
+
+function MenuPool:MultilineFormats(bool)
+ if bool ~= nil then
+ for _, Menu in pairs(self.Menus) do
+ Menu.Settings.MultilineFormats = tobool(bool)
+ end
+ end
+end
+
+function MenuPool:Audio(Attribute, Setting)
+ if Attribute ~= nil and Setting ~= nil then
+ for _, Menu in pairs(self.Menus) do
+ if Menu.Settings.Audio[Attribute] then
+ Menu.Settings.Audio[Attribute] = Setting
+ end
+ end
+ end
+end
+
+function MenuPool:WidthOffset(offset)
+ if tonumber(offset) then
+ for _, Menu in pairs(self.Menus) do
+ Menu:SetMenuWidthOffset(tonumber(offset))
+ end
+ end
+end
+
+function MenuPool:CounterPreText(str)
+ if str ~= nil then
+ for _, Menu in pairs(self.Menus) do
+ Menu.PageCounter.PreText = tostring(str)
+ end
+ end
+end
+
+function MenuPool:DisableInstructionalButtons(bool)
+ if bool ~= nil then
+ for _, Menu in pairs(self.Menus) do
+ Menu.Settings.InstructionalButtons = tobool(bool)
+ end
+ end
+end
+
+function MenuPool:MouseControlsEnabled(bool)
+ if bool ~= nil then
+ for _, Menu in pairs(self.Menus) do
+ Menu.Settings.MouseControlsEnabled = tobool(bool)
+ end
+ end
+end
+
+function MenuPool:RefreshIndex()
+ for _, Menu in pairs(self.Menus) do
+ Menu:RefreshIndex()
+ end
+end
+
+function MenuPool:ProcessMenus()
+ self:ProcessControl()
+ --self:ProcessMouse()
+ self:Draw()
+end
+
+function MenuPool:ProcessControl()
+ for _, Menu in pairs(self.Menus) do
+ if Menu:Visible() then
+ Menu:ProcessControl()
+ end
+ end
+end
+
+function MenuPool:ProcessMouse()
+ for _, Menu in pairs(self.Menus) do
+ if Menu:Visible() then
+ Menu:ProcessMouse()
+ end
+ end
+end
+
+function MenuPool:Draw()
+ for _, Menu in pairs(self.Menus) do
+ if Menu:Visible() then
+ Menu:Draw()
+ end
+ end
+end
+
+function MenuPool:IsAnyMenuOpen()
+ local open = false
+ for _, Menu in pairs(self.Menus) do
+ if Menu:Visible() then
+ open = true
+ break
+ end
+ end
+ return open
+end
+
+function MenuPool:CloseAllMenus()
+ for _, Menu in pairs(self.Menus) do
+ if Menu:Visible() then
+ Menu:Visible(false)
+ Menu.OnMenuClosed(Menu)
+ end
+ end
+end
+
+function MenuPool:SetBannerSprite(Sprite)
+ if Sprite() == "Sprite" then
+ for _, Menu in pairs(self.Menus) do
+ Menu:SetBannerSprite(Sprite)
+ end
+ end
+end
+
+function MenuPool:SetBannerRectangle(Rectangle)
+ if Rectangle() == "Rectangle" then
+ for _, Menu in pairs(self.Menus) do
+ Menu:SetBannerRectangle(Rectangle)
+ end
+ end
+end
+
+function MenuPool:TotalItemsPerPage(Value)
+ if tonumber(Value) then
+ for _, Menu in pairs(self.Menus) do
+ Menu.Pagination.Total = Value - 1
+ end
+ end
+end
+--[[
+ Wrappers
+--]]
+
+function NativeUI.CreatePool()
+ return MenuPool.New()
+end
+
+function NativeUI.CreateMenu(Title, Subtitle, X, Y, TxtDictionary, TxtName, titleTxt)
+ return UIMenu.New(Title, Subtitle, X, Y, TxtDictionary, TxtName, titleTxt)
+end
+
+function NativeUI.CreateItem(Text, Description)
+ return UIMenuItem.New(Text, Description)
+end
+
+function NativeUI.CreateColouredItem(Text, Description, MainColour, HighlightColour)
+ return UIMenuColouredItem.New(Text, Description, MainColour, HighlightColour)
+end
+
+function NativeUI.CreateCheckboxItem(Text, Check, Description)
+ return UIMenuCheckboxItem.New(Text, Check, Description)
+end
+
+function NativeUI.CreateListItem(Text, Items, Index, Description)
+ return UIMenuListItem.New(Text, Items, Index, Description)
+end
+
+function NativeUI.CreateSliderItem(Text, Items, Index, Description, Divider)
+ return UIMenuSliderItem.New(Text, Items, Index, Description, Divider)
+end
+
+function NativeUI.CreateProgressItem(Text, Items, Index, Description, Counter)
+ return UIMenuProgressItem.New(Text, Items, Index, Description, Counter)
+end
+
+function NativeUI.CreateHeritageWindow(Mum, Dad)
+ return UIMenuHeritageWindow.New(Mum, Dad)
+end
+
+function NativeUI.CreateGridPanel(TopText, LeftText, RightText, BottomText)
+ return UIMenuGridPanel.New(TopText, LeftText, RightText, BottomText)
+end
+
+function NativeUI.CreateColourPanel(Title, Colours)
+ return UIMenuColourPanel.New(Title, Colours)
+end
+
+function NativeUI.CreatePercentagePanel(MinText, MaxText)
+ return UIMenuPercentagePanel.New(MinText, MaxText)
+end
+
+function NativeUI.CreateSprite(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A)
+ return Sprite.New(TxtDictionary, TxtName, X, Y, Width, Height, Heading, R, G, B, A)
+end
+
+function NativeUI.CreateRectangle(X, Y, Width, Height, R, G, B, A)
+ return UIResRectangle.New(X, Y, Width, Height, R, G, B, A)
+end
+
+function NativeUI.CreateText(Text, X, Y, Scale, R, G, B, A, Font, Alignment, DropShadow, Outline, WordWrap)
+ return UIResText.New(Text, X, Y, Scale, R, G, B, A, Font, Alignment, DropShadow, Outline, WordWrap)
+end
diff --git a/resources/Interaction-Menu/functions.lua b/resources/Interaction-Menu/functions.lua
new file mode 100644
index 000000000..322906a2c
--- /dev/null
+++ b/resources/Interaction-Menu/functions.lua
@@ -0,0 +1,478 @@
+--[[
+─────────────────────────────────────────────────────────────────
+
+ SEM_InteractionMenu (functions.lua) - Created by Scott M
+ Current Version: v1.7.1 (Sep 2021)
+
+ Support: https://semdevelopment.com/discord
+
+ !!! Change vaules in the 'config.lua' !!!
+ DO NOT EDIT THIS IF YOU DON'T KNOW WHAT YOU ARE DOING
+
+─────────────────────────────────────────────────────────────────
+]]
+
+
+
+--General Functions
+function Notify(Text)
+ SetNotificationTextEntry('STRING')
+ AddTextComponentString(Text)
+ DrawNotification(true, true)
+end
+
+function NotifyHelp(Text)
+ SetTextComponentFormat('STRING')
+ AddTextComponentString(Text)
+ DisplayHelpTextFromStringLabel(0, 0, 1, -1)
+end
+
+function LoadAnimation(Dict)
+ while not HasAnimDictLoaded(Dict) do
+ RequestAnimDict(Dict)
+ Citizen.Wait(5)
+ end
+end
+
+function KeyboardInput(TextEntry, MaxStringLenght)
+ AddTextEntry('FMMC_KEY_TIP1', TextEntry)
+ DisplayOnscreenKeyboard(1, 'FMMC_KEY_TIP1', '', '', '', '', '', MaxStringLenght)
+ BlockInput = true
+
+ while UpdateOnscreenKeyboard() ~= 1 and UpdateOnscreenKeyboard() ~= 2 do
+ Citizen.Wait(0)
+ end
+
+ if UpdateOnscreenKeyboard() ~= 2 then
+ local Result = GetOnscreenKeyboardResult()
+ Citizen.Wait(500)
+ BlockInput = false
+ return Result
+ else
+ Citizen.Wait(500)
+ BlockInput = false
+ return nil
+ end
+end
+
+function GetClosestPlayer()
+ local Ped = PlayerPedId()
+
+ for _, Player in ipairs(GetActivePlayers()) do
+ if GetPlayerPed(Player) ~= GetPlayerPed(-1) then
+ local Ped2 = GetPlayerPed(Player)
+ local x, y, z = table.unpack(GetEntityCoords(Ped))
+ if (GetDistanceBetweenCoords(GetEntityCoords(Ped2), x, y, z) < 2) then
+ return GetPlayerServerId(Player)
+ end
+ end
+ end
+
+ Notify('~r~No Player Nearby!')
+ return false
+end
+
+function GetDistance(ID)
+ local Ped = GetPlayerPed(-1)
+ local Ped2 = GetPlayerPed(ID)
+ local x, y, z = table.unpack(GetEntityCoords(Ped))
+ return GetDistanceBetweenCoords(GetEntityCoords(Ped2), x, y, z)
+end
+
+--LEO Functions
+function ToggleRadar()
+ if Config.Radar ~= 0 then
+ if IsPedInAnyVehicle(GetPlayerPed(-1)) then
+ if GetVehicleClass(GetVehiclePedIsIn(GetPlayerPed(-1))) == 18 then
+ if GetPedInVehicleSeat(GetVehiclePedIsIn(GetPlayerPed(-1)) == -1) then
+ _MenuPool:CloseAllMenus()
+ if Config.Radar == 1 then
+ TriggerEvent('wk:openRemote')
+ elseif Config.Radar == 2 then
+ TriggerEvent('wk:radarRC')
+ end
+ else
+ Notify('~o~You need to be in the driver seat')
+ end
+ else
+ Notify('~o~You need to be in a police vehicle')
+ end
+ else
+ Notify('~o~You need to be in a vehicle')
+ end
+ end
+end
+
+function EnableShield()
+ ShieldActive = true
+ local Ped = GetPlayerPed(-1)
+ local PedPos = GetEntityCoords(Ped, false)
+
+ if IsPedInAnyVehicle(GetPlayerPed(-1), true) then
+ Notify('~r~You cannot be in a vehicle when getting your shield out!')
+ ShieldActive = false
+ return
+ end
+
+ RequestAnimDict('combat@gestures@gang@pistol_1h@beckon')
+ while not HasAnimDictLoaded('combat@gestures@gang@pistol_1h@beckon') do
+ Citizen.Wait(100)
+ end
+
+ TaskPlayAnim(Ped, 'combat@gestures@gang@pistol_1h@beckon', '0', 8.0, -8.0, -1, (2 + 16 + 32), 0.0, 0, 0, 0)
+
+ RequestModel(GetHashKey('prop_ballistic_shield'))
+ while not HasModelLoaded(GetHashKey('prop_ballistic_shield')) do
+ Citizen.Wait(100)
+ end
+
+ local shield = CreateObject(GetHashKey('prop_ballistic_shield'), PedPos.x, PedPos.y, PedPos.z, 1, 1, 1)
+ shieldEntity = shield
+ AttachEntityToEntity(shieldEntity, Ped, GetEntityBoneIndexByName(Ped, 'IK_L_Hand'), 0.0, -0.05, -0.10, -30.0, 180.0, 40.0, 0, 0, 1, 0, 0, 1)
+ SetWeaponAnimationOverride(Ped, 'Gang1H')
+
+ if HasPedGotWeapon(Ped, 'weapon_combatpistol', 0) or GetSelectedPedWeapon(Ped) == 'weapon_combatpistol' then
+ SetCurrentPedWeapon(Ped, 'weapon_combatpistol', 1)
+ HadPistol = true
+ else
+ GiveWeaponToPed(Ped, 'weapon_combatpistol', 300, 0, 1)
+ SetCurrentPedWeapon(Ped, 'weapon_combatpistol', 1)
+ HadPistol = false
+ end
+ SetEnableHandcuffs(Ped, true)
+end
+
+Citizen.CreateThread(function()
+ while true do
+ Citizen.Wait(1)
+
+ if ShieldActive == true then
+ DisableControlAction(1, 23, true) --F | Enter Vehicle
+ DisableControlAction(1, 75, true) --F | Exit Vehicle
+ end
+ end
+end)
+
+function DisableShield()
+ local Ped = GetPlayerPed(-1)
+ DeleteEntity(shieldEntity)
+ ClearPedTasksImmediately(Ped)
+ SetWeaponAnimationOverride(Ped, 'Default')
+ SetCurrentPedWeapon(Ped, 'weapon_unarmed', 1)
+
+ if not HadPistol then
+ RemoveWeaponFromPed(Ped, 'weapon_combatpistol')
+ end
+ SetEnableHandcuffs(Ped, false)
+ HadPistol = false
+ ShieldActive = false
+end
+
+
+
+--Civ Functions
+function Ad(Text, Name, Loc, File, ID)
+ SetNotificationTextEntry('STRING')
+ AddTextComponentString(Text)
+ EndTextCommandThefeedPostMessagetext(Loc, File, true, 1, Name, '~b~Advertisement #' .. ID)
+ DrawNotification(false, true)
+end
+
+
+
+--Vehicle Functions
+function SpawnVehicle(Veh, Name, Livery, Extras)
+ local Ped = GetPlayerPed( -1 )
+ if (DoesEntityExist(Ped) and not IsEntityDead(Ped)) then
+ local pos = GetEntityCoords(Ped)
+ if (IsPedSittingInAnyVehicle(Ped)) then
+ local Vehicle = GetVehiclePedIsIn(Ped, false)
+ if (GetPedInVehicleSeat(Vehicle, -1) == Ped) then
+ SetEntityAsMissionEntity(Vehicle, true, true )
+ DeleteVehicle(Vehicle)
+ end
+ end
+ end
+
+ local WaitTime = 0
+ local Model = GetHashKey(Veh)
+ RequestModel(Model)
+ while not HasModelLoaded(Model) do
+ CancelEvent()
+ RequestModel(Model)
+ Citizen.Wait(100)
+
+ WaitTime = WaitTime + 1
+
+ if WaitTime == 600 then
+ CancelEvent()
+ Notify('~r~Unable to load vehicle, please contact development!')
+ return
+ end
+ end
+ local x, y, z = table.unpack(GetEntityCoords(PlayerPedId(), false))
+ local Vehicle = CreateVehicle(Model, x + 2, y + 2, z + 1, GetEntityHeading(PlayerPedId()), true, false)
+ SetPedIntoVehicle(PlayerPedId(), Vehicle, -1)
+ SetVehicleDirtLevel(Vehicle, 0)
+ SetVehicleModKit(Vehicle, 0)
+ SetVehicleMod(Vehicle, 23, -1, false)
+ SetModelAsNoLongerNeeded(Model)
+ if Livery then
+ SetVehicleLivery(Vehicle, Livery)
+ end
+ if Extras then
+ for extraId = 0, 30 do
+ if DoesExtraExist(Vehicle, extraId) then
+ SetVehicleExtra(Vehicle, extraId, true)
+ end
+ end
+ for _, extra in pairs(Extras) do
+ SetVehicleExtra(Vehicle, extra, false)
+ end
+ end
+
+ if Name then
+ Notify('~b~Vehicle Spawned: ~g~' .. Name)
+ else
+ Notify('~b~Vehicle Spawned!')
+ end
+end
+
+function DeleteVehicle(entity)
+ Citizen.InvokeNative( 0xEA386986E786A54F, Citizen.PointerValueIntInitialized(entity))
+end
+
+
+
+--Ped Functions
+function LoadPed(Hash)
+ Citizen.CreateThread(function()
+ local Model = GetHashKey(Hash)
+ RequestModel(Model)
+
+ while not HasModelLoaded(Model) do
+ Wait(0)
+ end
+
+ if HasModelLoaded(Model) then
+ SetPlayerModel(PlayerId(), Model)
+ else
+ Notify('The model could not load - please contact development.')
+ end
+ end)
+end
+
+
+
+--Weapon Functions
+function GiveWeapon(Hash)
+ GiveWeaponToPed(GetPlayerPed(-1), GetHashKey(Hash), 999, false)
+end
+
+function AddWeaponComponent(WeaponHash, Component)
+ if HasPedGotWeapon(GetPlayerPed(-1), GetHashKey(WeaponHash), false) then
+ GiveWeaponComponentToPed(GetPlayerPed(-1), GetHashKey(WeaponHash), GetHashKey(Component))
+ end
+end
+
+
+
+--Prop Functions
+function SpawnProp(Object, Name)
+ local Player = PlayerPedId()
+ local Coords = GetEntityCoords(Player)
+ local Heading = GetEntityHeading(Player)
+
+ RequestModel(Object)
+ while not HasModelLoaded(Object) do
+ Citizen.Wait(0)
+ end
+
+ local OffsetCoords = GetOffsetFromEntityInWorldCoords(Player, 0.0, 0.75, 0.0)
+ local Prop = CreateObjectNoOffset(Object, OffsetCoords, false, true, false)
+ SetEntityHeading(Prop, Heading)
+ PlaceObjectOnGroundProperly(Prop)
+ SetEntityCollision(Prop, false, true)
+ SetEntityAlpha(Prop, 100)
+ FreezeEntityPosition(Prop, true)
+ SetModelAsNoLongerNeeded(Object)
+
+ Notify('Press ~g~E ~w~to place\nPress ~r~R ~w~to cancel')
+
+ Citizen.CreateThread(function()
+ while true do
+ Citizen.Wait(0)
+
+ local OffsetCoords = GetOffsetFromEntityInWorldCoords(Player, 0.0, 0.75, 0.0)
+ local Heading = GetEntityHeading(Player)
+
+ SetEntityCoordsNoOffset(Prop, OffsetCoords)
+ SetEntityHeading(Prop, Heading)
+ PlaceObjectOnGroundProperly(Prop)
+ DisableControlAction(1, 38, true) --E
+ DisableControlAction(1, 140, true) --R
+
+
+ if IsDisabledControlJustPressed(1, 38) then --E
+ local PropCoords = GetEntityCoords(Prop)
+ local PropHeading = GetEntityHeading(Prop)
+ DeleteObject(Prop)
+
+ RequestModel(Object)
+ while not HasModelLoaded(Object) do
+ Citizen.Wait(0)
+ end
+
+ local Prop = CreateObjectNoOffset(Object, PropCoords, true, true, true)
+ SetEntityHeading(Prop, PropHeading)
+ PlaceObjectOnGroundProperly(Prop)
+ FreezeEntityPosition(Prop, true)
+ SetEntityInvincible(Prop, true)
+ SetModelAsNoLongerNeeded(Object)
+ return
+ end
+
+ if IsDisabledControlJustPressed(1, 140) then --R
+ DeleteObject(Prop)
+ return
+ end
+ end
+ end)
+end
+
+function DeleteProp(Object)
+ local Hash = GetHashKey(Object)
+ local x, y, z = table.unpack(GetEntityCoords(PlayerPedId(), true))
+ if DoesObjectOfTypeExistAtCoords(x, y, z, 1.5, Hash, true) then
+ local Prop = GetClosestObjectOfType(x, y, z, 1.5, Hash, false, false, false)
+ DeleteObject(Prop)
+ Notify('~r~Prop Removed!')
+ end
+end
+
+function DeleteEntity(Entity)
+ Citizen.InvokeNative(0xAE3CBE5BF394C9C9, Citizen.PointerValueIntInitialized(Entity))
+end
+
+
+
+--Emote Functions
+function PlayEmote(Emote, Name)
+ if not DoesEntityExist(GetPlayerPed(-1)) then
+ return
+ end
+
+ if IsPedInAnyVehicle(GetPlayerPed(-1)) then
+ Notify('~r~Please exit the vehicle to use this emote!')
+ return
+ end
+
+ TaskStartScenarioInPlace(GetPlayerPed(-1), Emote, 0, true)
+ Notify('~b~Playing Emote: ~g~' .. Name)
+ EmotePlaying = true
+end
+
+function CancelEmote()
+ ClearPedTasks(GetPlayerPed(-1))
+ Notify('~r~Stopping Emote')
+ EmotePlaying = false
+end
+
+
+
+
+
+
+
+--Menu Restrictions
+function LEORestrict()
+ if Config.LEOAccess == 0 then
+ return false
+ elseif Config.LEOAccess == 1 then
+ return true
+ elseif Config.LEOAccess == 2 then
+ local Ped = GetEntityModel(GetPlayerPed(-1))
+
+ for _, LEOPeds in pairs(Config.LEOUniforms) do
+ local AllowedPed = GetHashKey(LEOPeds.spawncode)
+
+ if Ped == AllowedPed then
+ return true
+ end
+ end
+ elseif Config.LEOAccess == 3 then
+ return LEOOnduty
+ elseif Config.LEOAccess == 4 then
+ return LEOAce
+ else
+ return true
+ end
+end
+
+
+
+function FireRestrict()
+ if Config.FireAccess == 0 then
+ return false
+ elseif Config.FireAccess == 1 then
+ return true
+ elseif Config.FireAccess == 2 then
+ local Ped = GetEntityModel(GetPlayerPed(-1))
+
+ for _, FirePeds in pairs(Config.FireUniforms) do
+ local AllowedPed = GetHashKey(FirePeds.spawncode)
+
+ if Ped == AllowedPed then
+ return true
+ end
+ end
+ elseif Config.FireAccess == 3 then
+ return FireOnduty
+ elseif Config.FireAccess == 4 then
+ return FireAce
+ else
+ return true
+ end
+end
+
+
+
+function CivRestrict()
+ if Config.CivAccess == 0 then
+ return false
+ elseif Config.CivAccess == 1 then
+ return true
+ else
+ return true
+ end
+end
+
+
+
+function VehicleRestrict()
+ if Config.VehicleAccess == 0 then
+ return false
+ elseif Config.VehicleAccess == 1 then
+ return true
+ elseif Config.VehicleAccess == 2 then
+ if IsPedInAnyVehicle(GetPlayerPed(PlayerId()), false) then
+ return true
+ else
+ return false
+ end
+ else
+ return true
+ end
+end
+
+
+
+function EmoteRestrict()
+ if Config.EmoteAccess == 0 then
+ return false
+ elseif Config.EmoteAccess == 1 then
+ return true
+ else
+ return true
+ end
+end
diff --git a/resources/Interaction-Menu/fxmanifest.lua b/resources/Interaction-Menu/fxmanifest.lua
new file mode 100644
index 000000000..dcd4a8f0a
--- /dev/null
+++ b/resources/Interaction-Menu/fxmanifest.lua
@@ -0,0 +1,43 @@
+--[[
+──────────────────────────────────────────────────────────────────
+
+ SEM_InteractionMenu (fxmanifest.lua) - Created by Scott M
+ Current Version: v1.7.1 (Sep 2021)
+
+ Support: https://semdevelopment.com/discord
+
+ !!! Change vaules in the 'config.lua' !!!
+ DO NOT EDIT THIS IF YOU DON'T KNOW WHAT YOU ARE DOING
+
+──────────────────────────────────────────────────────────────────
+]]
+
+
+
+fx_version 'cerulean'
+games {'gta5'}
+
+--DO NOT REMOVE THESE
+title 'SEM_InteractionMenu'
+description 'Multi Purpose Interaction Menu'
+author 'Scott M [SEM Development]'
+version 'v1.7.1' --This is required for the version checker, DO NOT change or remove
+
+client_scripts {
+ 'dependencies/NativeUI.lua',
+ 'client.lua',
+ 'config.lua',
+ 'functions.lua',
+ 'menu.lua',
+}
+
+server_scripts {
+ 'config.lua',
+ 'server.lua',
+ 'functions.lua',
+}
+
+exports {
+ 'IsOndutyLEO',
+ 'IsOndutyFire',
+}
diff --git a/resources/Interaction-Menu/menu.lua b/resources/Interaction-Menu/menu.lua
new file mode 100644
index 000000000..2bad19a07
--- /dev/null
+++ b/resources/Interaction-Menu/menu.lua
@@ -0,0 +1,1099 @@
+--[[
+───────────────────────────────────────────────────────────────
+
+ SEM_InteractionMenu (menu.lua) - Created by Scott M
+ Current Version: v1.7.1 (Sep 2021)
+
+ Support | https://semdevelopment.com/discord
+
+ !!! Change vaules in the 'config.lua' !!!
+ DO NOT EDIT THIS IF YOU DON'T KNOW WHAT YOU ARE DOING
+
+───────────────────────────────────────────────────────────────
+]]
+
+
+
+local MenuOri = 0
+if Config.MenuOrientation == 0 then
+ MenuOri = 0
+elseif Config.MenuOrientation == 1 then
+ MenuOri = 1320
+else
+ MenuOri = 0
+end
+
+
+_MenuPool = NativeUI.CreatePool()
+MainMenu = NativeUI.CreateMenu()
+
+
+
+
+
+function Menu()
+ local MenuTitle = ''
+ if Config.MenuTitle == 0 then
+ MenuTitle = 'Interaction Menu'
+ elseif Config.MenuTitle == 1 then
+ MenuTitle = GetPlayerName(source)
+ elseif Config.MenuTitle == 2 then
+ MenuTitle = Config.MenuTitleCustom
+ else
+ MenuTitle = 'Interaction Menu'
+ end
+
+
+
+ _MenuPool:Remove()
+ _MenuPool = NativeUI.CreatePool()
+ MainMenu = NativeUI.CreateMenu(MenuTitle, GetResourceMetadata(GetCurrentResourceName(), 'title', 0) .. ' ~y~' .. GetResourceMetadata(GetCurrentResourceName(), 'version', 0), MenuOri)
+ _MenuPool:Add(MainMenu)
+ MainMenu:SetMenuWidthOffset(Config.MenuWidth)
+ collectgarbage()
+
+ MainMenu:SetMenuWidthOffset(Config.MenuWidth)
+ _MenuPool:ControlDisablingEnabled(false)
+ _MenuPool:MouseControlsEnabled(false)
+
+
+
+
+
+ if LEORestrict() then
+ local LEOMenu = _MenuPool:AddSubMenu(MainMenu, 'LEO Toolbox', 'Law Enforcement Related Menu', true)
+ LEOMenu:SetMenuWidthOffset(Config.MenuWidth)
+ local LEOActions = _MenuPool:AddSubMenu(LEOMenu, 'Actions', '', true)
+ LEOActions:SetMenuWidthOffset(Config.MenuWidth)
+ local Cuff = NativeUI.CreateItem('Cuff', 'Cuff/Uncuff the closest player')
+ local Drag = NativeUI.CreateItem('Drag', 'Drag/Undrag the closest player')
+ local Seat = NativeUI.CreateItem('Seat', 'Place a player in the closest vehicle')
+ local Unseat = NativeUI.CreateItem('Unseat', 'Remove a player from the closest vehicle')
+ local Radar = NativeUI.CreateItem('Radar', 'Toggle the radar menu')
+ local Inventory = NativeUI.CreateItem('Inventory', 'Search the closest player\'s inventory')
+ local BAC = NativeUI.CreateItem('BAC', 'Test the BAC level of the closest player')
+ local Jail = NativeUI.CreateItem('Jail', 'Jail a player')
+ local Unjail = NativeUI.CreateItem('Unjail', 'Unjail a player')
+ SpikeLengths = {1, 2, 3, 4, 5}
+ local Spikes = NativeUI.CreateListItem('Deploy Spikes', SpikeLengths, 1, 'Places spike strips on the ground')
+ local DelSpikes = NativeUI.CreateItem('Remove Spikes', 'Remove spike strips placed on the ground')
+ local Shield = NativeUI.CreateItem('Toggle Shield', 'Toggle the bulletproof shield')
+ local CarbineRifle = NativeUI.CreateItem('Toggle Carbine', 'Toggle your carbine rifle')
+ local Shotgun = NativeUI.CreateItem('Toggle Shotgun', 'Toggle your pump shotgun')
+ PropsList = {}
+ for _, Prop in pairs(Config.Props) do
+ table.insert(PropsList, Prop.name)
+ end
+ local Props = NativeUI.CreateListItem('Spawn Props', PropsList, 1, 'Spawn props on the ground')
+ local RemoveProps = NativeUI.CreateItem('Remove Props', 'Remove the closest prop')
+ LEOActions:AddItem(Cuff)
+ LEOActions:AddItem(Drag)
+ LEOActions:AddItem(Seat)
+ LEOActions:AddItem(Unseat)
+ if Config.Radar ~= 0 then
+ LEOActions:AddItem(Radar)
+ end
+ LEOActions:AddItem(Inventory)
+ LEOActions:AddItem(BAC)
+ if Config.LEOJail then
+ LEOActions:AddItem(Jail)
+ if UnjailAllowed then
+ LEOActions:AddItem(Unjail)
+ end
+ end
+ LEOActions:AddItem(Spikes)
+ LEOActions:AddItem(DelSpikes)
+ LEOActions:AddItem(Shield)
+ if Config.UnrackWeapons == 1 or Config.UnrackWeapons == 2 then
+ LEOActions:AddItem(CarbineRifle)
+ LEOActions:AddItem(Shotgun)
+ end
+ if Config.DisplayProps then
+ LEOActions:AddItem(Props)
+ LEOActions:AddItem(RemoveProps)
+ end
+ Cuff.Activated = function(ParentMenu, SelectedItem)
+ local player = GetClosestPlayer()
+ if player ~= false then
+ TriggerServerEvent('SEM_InteractionMenu:CuffNear', player)
+ end
+ end
+ Drag.Activated = function(ParentMenu, SelectedItem)
+ local player = GetClosestPlayer()
+ if player ~= false then
+ TriggerServerEvent('SEM_InteractionMenu:DragNear', player)
+ end
+ end
+ Seat.Activated = function(ParentMenu, SelectedItem)
+ local Veh = GetVehiclePedIsIn(Ped, true)
+
+ local player = GetClosestPlayer()
+ if player ~= false then
+ TriggerServerEvent('SEM_InteractionMenu:SeatNear', player, Veh)
+ end
+ end
+ Unseat.Activated = function(ParentMenu, SelectedItem)
+ if IsPedInAnyVehicle(GetPlayerPed(-1), true) then
+ Notify('~o~You need to be outside of the vehicle')
+ return
+ end
+
+ local player = GetClosestPlayer()
+ if player ~= false then
+ TriggerServerEvent('SEM_InteractionMenu:UnseatNear', player)
+ end
+ end
+ Radar.Activated = function(ParentMenu, SelectedItem)
+ ToggleRadar()
+ end
+ Inventory.Activated = function(ParentMenu, SelectedItem)
+ local player = GetClosestPlayer()
+ if player ~= false then
+ Notify('~b~Searching ...')
+ TriggerServerEvent('SEM_InteractionMenu:InventorySearch', player)
+ end
+ end
+ BAC.Activated = function(ParentMenu, SelectedItem)
+ local player = GetClosestPlayer()
+ if player ~= false then
+ Notify('~b~Testing ...')
+ TriggerServerEvent('SEM_InteractionMenu:BACTest', player)
+ end
+ end
+ Jail.Activated = function(ParentMenu, SelectedItem)
+ local PlayerID = tonumber(KeyboardInput('Player ID:', 10))
+ if PlayerID == nil then
+ Notify('~r~Please enter a player ID')
+ return
+ end
+
+ local JailTime = tonumber(KeyboardInput('Time: (Seconds) - Max Time: ' .. Config.MaxJailTime .. ' | Default Time: 30', string.len(Config.MaxJailTime)))
+ if JailTime == nil then
+ JailTime = 30
+ end
+ if JailTime > Config.MaxJailTime then
+ Notify('~y~Exceeded Max Time\nMax Time: ' .. Config.MaxJailTime .. ' seconds')
+ JailTime = Config.MaxJailTime
+ end
+
+ Notify('Player Jailed for ~b~' .. JailTime .. ' seconds')
+ TriggerServerEvent('SEM_InteractionMenu:Jail', PlayerID, JailTime)
+ end
+ Unjail.Activated = function(ParentMenu, SelectedItem)
+ local PlayerID = tonumber(KeyboardInput('Player ID:', 10))
+ if PlayerID == nil then
+ Notify('~r~Please enter a player ID')
+ return
+ end
+
+ TriggerServerEvent('SEM_InteractionMenu:Unjail', PlayerID)
+ end
+ DelSpikes.Activated = function(ParentMenu, SelectedItem)
+ TriggerEvent('SEM_InteractionMenu:Spikes-DeleteSpikes')
+ end
+ Shield.Activated = function(ParentMenu, SelectedItem)
+ if ShieldActive then
+ DisableShield()
+ else
+ EnableShield()
+ end
+ end
+ CarbineRifle.Activated = function(ParentMenu, SelectedItem)
+ if (GetVehicleClass(GetVehiclePedIsIn(GetPlayerPed(-1))) == 18) then
+ CarbineEquipped = not CarbineEquipped
+ ShotgunEquipped = false
+ elseif (GetVehicleClass(GetVehiclePedIsIn(GetPlayerPed(-1))) ~= 18) then
+ Notify('~r~You Must be in a Police Vehicle to rack/unrack your Carbine Rifle')
+ return
+ end
+
+ if CarbineEquipped then
+ Notify('~g~Carbine Rifle Equipped')
+ GiveWeapon('weapon_carbinerifle')
+ AddWeaponComponent('weapon_carbinerifle', 'component_at_ar_flsh')
+ AddWeaponComponent('weapon_carbinerifle', 'component_at_ar_afgrip')
+ else
+ Notify('~y~Carbine Rifle Unequipped')
+ RemoveWeaponFromPed(GetPlayerPed(-1), 'weapon_carbinerifle')
+ end
+ end
+ Shotgun.Activated = function(ParentMenu, SelectedItem)
+ if (GetVehicleClass(GetVehiclePedIsIn(GetPlayerPed(-1))) == 18) then
+ ShotgunEquipped = not ShotgunEquipped
+ CarbineEquipped = false
+ elseif (GetVehicleClass(GetVehiclePedIsIn(GetPlayerPed(-1))) ~= 18) then
+ Notify('~r~You Must be in a Police Vehicle to rack/unrack your Shotgun')
+ return
+ end
+
+ if ShotgunEquipped then
+ Notify('~g~Shotgun Equipped')
+ GiveWeapon('weapon_pumpshotgun')
+ AddWeaponComponent('weapon_pumpshotgun', 'component_at_ar_flsh')
+ else
+ Notify('~y~Shotgun Unequipped')
+ RemoveWeaponFromPed(GetPlayerPed(-1), 'weapon_pumpshotgun')
+ end
+ end
+ LEOActions.OnListSelect = function(sender, item, index)
+ if item == Spikes then
+ TriggerEvent('SEM_InteractionMenu:Spikes-SpawnSpikes', tonumber(index))
+ elseif item == Props then
+ for _, Prop in pairs(Config.Props) do
+ if Prop.name == item:IndexToItem(index) then
+ SpawnProp(Prop.spawncode, Prop.name)
+ end
+ end
+ end
+ end
+ RemoveProps.Activated = function(ParentMenu, SelectedItem)
+ for _, Prop in pairs(Config.Props) do
+ DeleteProp(Prop.spawncode)
+ end
+ end
+
+ if Config.DisplayBackup then
+ local LEOBackup = _MenuPool:AddSubMenu(LEOMenu, 'Backup', '', true)
+ LEOBackup:SetMenuWidthOffset(Config.MenuWidth)
+ --[[
+ Code 1 Backup | No Lights or Siren
+ Code 2 Backup | Only Lights
+ Code 3 Backup | Lights and Siren
+ Code 99 Backup | All Available Unit Responde Code 3
+ ]]
+ local BK1 = NativeUI.CreateItem('Code 1', 'Call Code 1 Backup to your location')
+ local BK2 = NativeUI.CreateItem('Code 2', 'Call Code 2 Backup to your location')
+ local BK3 = NativeUI.CreateItem('Code 3', 'Call Code 3 Backup to your location')
+ local BK99 = NativeUI.CreateItem('Code 99', 'Call Code 99 Backup to your location')
+ local PanicBTN = NativeUI.CreateItem('~r~Panic Button', 'Officer Panic Button')
+ LEOBackup:AddItem(BK1)
+ LEOBackup:AddItem(BK2)
+ LEOBackup:AddItem(BK3)
+ LEOBackup:AddItem(BK99)
+ LEOBackup:AddItem(PanicBTN)
+ BK1.Activated = function(ParentMenu, SelectedItem)
+ local Coords = GetEntityCoords(GetPlayerPed(-1))
+ local Street1, Street2 = GetStreetNameAtCoord(Coords.x, Coords.y, Coords.z)
+ local StreetName = GetStreetNameFromHashKey(Street1)
+
+ TriggerServerEvent('SEM_InteractionMenu:Backup', 1, StreetName, Coords)
+ end
+ BK2.Activated = function(ParentMenu, SelectedItem)
+ local Coords = GetEntityCoords(GetPlayerPed(-1))
+ local Street1, Street2 = GetStreetNameAtCoord(Coords.x, Coords.y, Coords.z)
+ local StreetName = GetStreetNameFromHashKey(Street1)
+
+ TriggerServerEvent('SEM_InteractionMenu:Backup', 2, StreetName, Coords)
+ end
+ BK3.Activated = function(ParentMenu, SelectedItem)
+ local Coords = GetEntityCoords(GetPlayerPed(-1))
+ local Street1, Street2 = GetStreetNameAtCoord(Coords.x, Coords.y, Coords.z)
+ local StreetName = GetStreetNameFromHashKey(Street1)
+
+ TriggerServerEvent('SEM_InteractionMenu:Backup', 3, StreetName, Coords)
+ end
+ BK99.Activated = function(ParentMenu, SelectedItem)
+ local Coords = GetEntityCoords(GetPlayerPed(-1))
+ local Street1, Street2 = GetStreetNameAtCoord(Coords.x, Coords.y, Coords.z)
+ local StreetName = GetStreetNameFromHashKey(Street1)
+
+ TriggerServerEvent('SEM_InteractionMenu:Backup', 99, StreetName, Coords)
+ end
+ PanicBTN.Activated = function(ParentMenu, SelectedItem)
+ local Coords = GetEntityCoords(GetPlayerPed(-1))
+ local Street1, Street2 = GetStreetNameAtCoord(Coords.x, Coords.y, Coords.z)
+ local StreetName = GetStreetNameFromHashKey(Street1)
+
+ TriggerServerEvent('SEM_InteractionMenu:Backup', 'panic', StreetName, Coords)
+ end
+ end
+
+ if Config.ShowStations then
+ local LEOStation = _MenuPool:AddSubMenu(LEOMenu, 'Stations', '', true)
+ LEOStation:SetMenuWidthOffset(Config.MenuWidth)
+ for _, Station in pairs(Config.LEOStations) do
+ local StationCategory = _MenuPool:AddSubMenu(LEOStation, Station.name, '', true)
+ StationCategory:SetMenuWidthOffset(Config.MenuWidth)
+ local SetWaypoint = NativeUI.CreateItem('Set Waypoint', 'Set a waypoint to the station')
+ local Teleport = NativeUI.CreateItem('Teleport', 'Teleport to the station')
+ StationCategory:AddItem(SetWaypoint)
+ if Config.AllowStationTeleport then
+ StationCategory:AddItem(Teleport)
+ end
+ SetWaypoint.Activated = function(ParentMenu, SelectedItem)
+ SetNewWaypoint(Station.coords.x, Station.coords.y)
+ end
+ Teleport.Activated = function(ParentMenu, SelectedItem)
+ SetEntityCoords(PlayerPedId(), Station.coords.x, Station.coords.y, Station.coords.z)
+ SetEntityHeading(PlayerPedId(), Station.coords.h)
+ end
+ end
+ end
+
+ if Config.DisplayLEOUniforms or Config.DisplayLEOLoadouts then
+ local LEOLoadouts = _MenuPool:AddSubMenu(LEOMenu, 'Loadouts', '', true)
+ LEOLoadouts:SetMenuWidthOffset(Config.MenuWidth)
+ UniformsList = {}
+ for _, Uniform in pairs(Config.LEOUniforms) do
+ table.insert(UniformsList, Uniform.name)
+ end
+
+ LoadoutsList = {}
+ for Name, Loadout in pairs(Config.LEOLoadouts) do
+ table.insert(LoadoutsList, Name)
+ end
+
+ local Uniforms = NativeUI.CreateListItem('Uniforms', UniformsList, 1, 'Spawn LEO uniforms')
+ local Loadouts = NativeUI.CreateListItem('Loadouts', LoadoutsList, 1, 'Spawn LEO weapon loadouts')
+ if Config.DisplayLEOUniforms then
+ LEOLoadouts:AddItem(Uniforms)
+ end
+ if Config.DisplayLEOLoadouts then
+ LEOLoadouts:AddItem(Loadouts)
+ end
+ LEOLoadouts.OnListSelect = function(sender, item, index)
+ if item == Uniforms then
+ for _, Uniform in pairs(Config.LEOUniforms) do
+ if Uniform.name == item:IndexToItem(index) then
+ LoadPed(Uniform.spawncode)
+ Notify('~b~Uniform Spawned: ~g~' .. Uniform.name)
+ end
+ end
+ end
+
+
+
+ if item == Loadouts then
+ for Name, Loadout in pairs(Config.LEOLoadouts) do
+ if Name == item:IndexToItem(index) then
+ SetEntityHealth(GetPlayerPed(-1), 200)
+ RemoveAllPedWeapons(GetPlayerPed(-1), true)
+ AddArmourToPed(GetPlayerPed(-1), 100)
+
+ for _, Weapon in pairs(Loadout) do
+ GiveWeapon(Weapon.weapon)
+
+ for _, Component in pairs(Weapon.components) do
+ AddWeaponComponent(Weapon.weapon, Component)
+ end
+ end
+
+ Notify('~b~Loadout Spawned: ~g~' .. Name)
+ end
+ end
+ end
+ end
+ end
+
+ if Config.ShowLEOVehicles then
+ local LEOVehicles = _MenuPool:AddSubMenu(LEOMenu, 'Vehicles', '', true)
+ LEOVehicles:SetMenuWidthOffset(Config.MenuWidth)
+
+ for Name, Category in pairs(Config.LEOVehiclesCategories) do
+ local LEOCategory = _MenuPool:AddSubMenu(LEOVehicles, Name, '', true)
+ LEOCategory:SetMenuWidthOffset(Config.MenuWidth)
+ for _, Vehicle in pairs(Category) do
+ local LEOVehicle = NativeUI.CreateItem(Vehicle.name, '')
+ LEOCategory:AddItem(LEOVehicle)
+ if Config.ShowLEOSpawnCode then
+ LEOVehicle:RightLabel(Vehicle.spawncode)
+ end
+ LEOVehicle.Activated = function(ParentMenu, SelectedItem)
+ SpawnVehicle(Vehicle.spawncode, Vehicle.name, Vehicle.livery, Vehicle.extras)
+ end
+ end
+ end
+ end
+
+ if Config.DisplayTrafficManager then
+ local LEOTrafficManager = _MenuPool:AddSubMenu(LEOMenu, 'Traffic Manager', '', true)
+ LEOTrafficManager:SetMenuWidthOffset(Config.MenuWidth)
+
+ TMSize = 10.0
+ TMSpeed = 0.0
+ RaduiesNames = {}
+ Raduies = {
+ {name = '10m', size = 10.0},
+ {name = '20m', size = 20.0},
+ {name = '30m', size = 30.0},
+ {name = '40m', size = 40.0},
+ {name = '50m', size = 50.0},
+ {name = '60m', size = 60.0},
+ {name = '70m', size = 70.0},
+ {name = '80m', size = 80.0},
+ {name = '90m', size = 90.0},
+ {name = '100m', size = 100.0},
+ }
+ SpeedsNames = {}
+ Speeds = {
+ {name = '0 mph', speed = 0.0},
+ {name = '5 mph', speed = 5.0},
+ {name = '10 mph', speed = 10.0},
+ {name = '15 mph', speed = 15.0},
+ {name = '20 mph', speed = 20.0},
+ {name = '25 mph', speed = 25.0},
+ {name = '30 mph', speed = 30.0},
+ {name = '40 mph', speed = 40.0},
+ {name = '50 mph', speed = 50.0},
+ }
+
+ for _, RaduisInfo in pairs(Raduies) do
+ table.insert(RaduiesNames, RaduisInfo.name)
+ end
+ for _, SpeedsInfo in pairs(Speeds) do
+ table.insert(SpeedsNames, SpeedsInfo.name)
+ end
+
+ local Radius = NativeUI.CreateListItem('Radius', RaduiesNames, 1, '')
+ local Speed = NativeUI.CreateListItem('Speed', SpeedsNames, 1, '')
+ local TMCreate = NativeUI.CreateItem('Create Speed Zone', '')
+ local TMDelete = NativeUI.CreateItem('Delete Speed Zone', '')
+ LEOTrafficManager:AddItem(Radius)
+ LEOTrafficManager:AddItem(Speed)
+ LEOTrafficManager:AddItem(TMCreate)
+ LEOTrafficManager:AddItem(TMDelete)
+ Radius.OnListChanged = function(sender, item, index)
+ TMSize = Raduies[index].size
+ end
+ Speed.OnListChanged = function(sender, item, index)
+ TMSpeed = Speeds[index].speed
+ end
+ TMCreate.Activated = function(ParentMenu, SelectedItem)
+ if Zone == nil then
+ Zone = AddSpeedZoneForCoord(GetEntityCoords(PlayerPedId()), TMSize, TMSpeed, false)
+ Area = AddBlipForRadius(GetEntityCoords(PlayerPedId()), TMSize)
+ SetBlipAlpha(Area, 100)
+ Notify('~g~Speed Zone Created')
+ else
+ Notify('~y~You already have a Speed Zone created')
+ end
+ end
+ TMDelete.Activated = function(ParentMenu, SelectedItem)
+ if Zone ~= nil then
+ RemoveSpeedZone(Zone)
+ RemoveBlip(Area)
+ Zone = nil
+ Notify('~r~Speed Zone Deleted')
+ else
+ Notify('~y~You don\'t have a Speed Zone')
+ end
+ end
+ end
+ end
+
+
+
+
+ if FireRestrict() then
+ local FireMenu = _MenuPool:AddSubMenu(MainMenu, 'Fire Toolbox', 'Fire Related Menu', true)
+ FireMenu:SetMenuWidthOffset(Config.MenuWidth)
+ local FireActions = _MenuPool:AddSubMenu(FireMenu, 'Actions', '', true)
+ FireActions:SetMenuWidthOffset(Config.MenuWidth)
+ local Drag = NativeUI.CreateItem('Drag', 'Drag/Undrag the closest player')
+ local Seat = NativeUI.CreateItem('Seat', 'Place a player in the closest vehicle')
+ local Unseat = NativeUI.CreateItem('Unseat', 'Remove a player from the closest vehicle')
+ FireActions:AddItem(Drag)
+ FireActions:AddItem(Seat)
+ FireActions:AddItem(Unseat)
+ Drag.Activated = function(ParentMenu, SelectedItem)
+ local player = GetClosestPlayer()
+ if player ~= false then
+ TriggerServerEvent('SEM_InteractionMenu:DragNear', player)
+ end
+ end
+ Seat.Activated = function(ParentMenu, SelectedItem)
+ local player = GetClosestPlayer()
+ if player ~= false then
+ TriggerServerEvent('SEM_InteractionMenu:SeatNear', player, Veh)
+ end
+ end
+ Unseat.Activated = function(ParentMenu, SelectedItem)
+ if IsPedInAnyVehicle(GetPlayerPed(-1), true) then
+ Notify('~o~You need to be outside of the vehicle')
+ return
+ end
+
+ local player = GetClosestPlayer()
+ if player ~= false then
+ TriggerServerEvent('SEM_InteractionMenu:UnseatNear', player)
+ end
+ end
+ if Config.FireHospital then
+ local HospitalLocations = _MenuPool:AddSubMenu(FireActions, 'Hospitalize', '', true)
+ HospitalLocations:SetMenuWidthOffset(Config.MenuWidth)
+ for HospitalName, HospitalInfo in pairs(Config.HospitalLocation) do
+ local Hospitalize = NativeUI.CreateItem(HospitalName, 'Hospitalize a player')
+ HospitalLocations:AddItem(Hospitalize)
+ Hospitalize.Activated = function(ParentMenu, SelectedItem)
+ local PlayerID = tonumber(KeyboardInput('Player ID:', 10))
+ if PlayerID == nil then
+ Notify('~r~Please enter a player ID')
+ return
+ end
+
+ local HospitalTime = tonumber(KeyboardInput('Time: (Seconds) - Max Time: ' .. Config.MaxHospitalTime .. ' | Default Time: 30', 3))
+ if HospitalTime == nil then
+ HospitalTime = 30
+ end
+ if HospitalTime > Config.MaxHospitalTime then
+ Notify('~y~Exceeded Max Time\nMax Time: ' .. Config.MaxHospitalTime .. ' seconds')
+ HospitalTime = Config.MaxHospitalTime
+ end
+
+ Notify('Player Hospitalized for ~b~' .. HospitalTime .. ' seconds')
+ TriggerServerEvent('SEM_InteractionMenu:Hospitalize', PlayerID, HospitalTime, HospitalInfo)
+ end
+ end
+ local Unhospitalize = NativeUI.CreateItem('Unhospitalize', 'Unhospitalize a player')
+ if UnhospitalAllowed then
+ FireActions:AddItem(Unhospitalize)
+ end
+ Unhospitalize.Activated = function(ParentMenu, SelectedItem)
+ local PlayerID = tonumber(KeyboardInput('Player ID:', 10))
+ if PlayerID == nil then
+ Notify('~r~Please enter a player ID')
+ return
+ end
+
+ TriggerServerEvent('SEM_InteractionMenu:Unhospitalize', PlayerID)
+ end
+ end
+ PropsList = {}
+ for _, Prop in pairs(Config.Props) do
+ table.insert(PropsList, Prop.name)
+ end
+ local Props = NativeUI.CreateListItem('Spawn Props', PropsList, 1, 'Spawn props on the ground')
+ local RemoveProps = NativeUI.CreateItem('Remove Props', 'Remove the closest prop')
+ FireActions:AddItem(Props)
+ FireActions:AddItem(RemoveProps)
+ FireActions.OnListSelect = function(sender, item, index)
+ if item == Props then
+ for _, Prop in pairs(Config.Props) do
+ if Prop.name == item:IndexToItem(index) then
+ SpawnProp(Prop.spawncode, Prop.name)
+ end
+ end
+ end
+ end
+ RemoveProps.Activated = function(ParentMenu, SelectedItem)
+ for _, Prop in pairs(Config.Props) do
+ DeleteProp(Prop.spawncode)
+ end
+ end
+
+ if Config.ShowStations then
+ local FireEMSStation = _MenuPool:AddSubMenu(FireMenu, 'Stations', '', true)
+ FireEMSStation:SetMenuWidthOffset(Config.MenuWidth)
+ local FireStation = _MenuPool:AddSubMenu(FireEMSStation, 'Fire Stations', '', true)
+ FireStation:SetMenuWidthOffset(Config.MenuWidth)
+ for _, Station in pairs(Config.FireStations) do
+ local StationCategory = _MenuPool:AddSubMenu(FireStation, Station.name, '', true)
+ StationCategory:SetMenuWidthOffset(Config.MenuWidth)
+ local SetWaypoint = NativeUI.CreateItem('Set Waypoint', 'Set a waypoint to the station')
+ local Teleport = NativeUI.CreateItem('Teleport', 'Teleport to the station')
+ StationCategory:AddItem(SetWaypoint)
+ if Config.AllowStationTeleport then
+ StationCategory:AddItem(Teleport)
+ end
+ SetWaypoint.Activated = function(ParentMenu, SelectedItem)
+ SetNewWaypoint(Station.coords.x, Station.coords.y)
+ end
+ Teleport.Activated = function(ParentMenu, SelectedItem)
+ SetEntityCoords(PlayerPedId(), Station.coords.x, Station.coords.y, Station.coords.z)
+ SetEntityHeading(PlayerPedId(), Station.coords.h)
+ end
+ end
+
+ local EMSStation = _MenuPool:AddSubMenu(FireEMSStation, 'Hospitals', '', true)
+ EMSStation:SetMenuWidthOffset(Config.MenuWidth)
+ for _, Station in pairs(Config.HospitalStations) do
+ local StationCategory = _MenuPool:AddSubMenu(EMSStation, Station.name, '', true)
+ StationCategory:SetMenuWidthOffset(Config.MenuWidth)
+ local SetWaypoint = NativeUI.CreateItem('Set Waypoint', 'Set a waypoint to the hospital')
+ local Teleport = NativeUI.CreateItem('Teleport', 'Teleport to the hospital')
+ StationCategory:AddItem(SetWaypoint)
+ if Config.AllowStationTeleport then
+ StationCategory:AddItem(Teleport)
+ end
+ SetWaypoint.Activated = function(ParentMenu, SelectedItem)
+ SetNewWaypoint(Station.coords.x, Station.coords.y)
+ end
+ Teleport.Activated = function(ParentMenu, SelectedItem)
+ SetEntityCoords(PlayerPedId(), Station.coords.x, Station.coords.y, Station.coords.z)
+ SetEntityHeading(PlayerPedId(), Station.coords.h)
+ end
+ end
+ end
+
+ if Config.DisplayFireUniforms or Config.DisplayFireLoadouts then
+ local FireLoadouts = _MenuPool:AddSubMenu(FireMenu, 'Loadouts', '', true)
+ FireLoadouts:SetMenuWidthOffset(Config.MenuWidth)
+ UniformsList = {}
+ for _, Uniform in pairs(Config.FireUniforms) do
+ table.insert(UniformsList, Uniform.name)
+ end
+
+ LoadoutsList = {
+ 'Clear',
+ 'Standard',
+ }
+ local Uniforms = NativeUI.CreateListItem('Uniforms', UniformsList, 1, 'Spawn Fire uniforms')
+ local Loadouts = NativeUI.CreateListItem('Loadouts', LoadoutsList, 1, 'Spawns Fire weapon loadouts')
+ if Config.DisplayFireUniforms then
+ FireLoadouts:AddItem(Uniforms)
+ end
+ if Config.DisplayFireLoadouts then
+ FireLoadouts:AddItem(Loadouts)
+ end
+ FireLoadouts.OnListSelect = function(sender, item, index)
+ if item == Uniforms then
+ for _, Uniform in pairs(Config.FireUniforms) do
+ if Uniform.name == item:IndexToItem(index) then
+ LoadPed(Uniform.spawncode)
+ Notify('~b~Uniform Spawned: ~g~' .. Uniform.name)
+ end
+ end
+ end
+
+
+
+ if item == Loadouts then
+ local SelectedLoadout = item:IndexToItem(index)
+ if SelectedLoadout == 'Clear' then
+ SetEntityHealth(GetPlayerPed(-1), 200)
+ RemoveAllPedWeapons(GetPlayerPed(-1), true)
+ Notify('~r~All Weapons Cleared!')
+ elseif SelectedLoadout == 'Standard' then
+ SetEntityHealth(GetPlayerPed(-1), 200)
+ RemoveAllPedWeapons(GetPlayerPed(-1), true)
+ AddArmourToPed(GetPlayerPed(-1), 100)
+ GiveWeapon('weapon_flashlight')
+ GiveWeapon('weapon_fireextinguisher')
+ GiveWeapon('weapon_flare')
+ GiveWeapon('weapon_stungun')
+ Notify('~b~Loadout Spawned: ~g~' .. SelectedLoadout)
+ end
+ end
+ end
+ end
+
+ if Config.ShowFireVehicles then
+ local FireVehicles = _MenuPool:AddSubMenu(FireMenu, 'Vehicles', '', true)
+ FireVehicles:SetMenuWidthOffset(Config.MenuWidth)
+
+ for _, Vehicle in pairs(Config.FireVehicles) do
+ local FireVehicle = NativeUI.CreateItem(Vehicle.name, '')
+ FireVehicles:AddItem(FireVehicle)
+ if Config.ShowFireSpawnCode then
+ FireVehicle:RightLabel(Vehicle.spawncode)
+ end
+ FireVehicle.Activated = function(ParentMenu, SelectedItem)
+ SpawnVehicle(Vehicle.spawncode, Vehicle.name, Vehicle.livery, Vehicle.extras)
+ end
+ end
+ end
+ end
+
+
+
+
+ if CivRestrict() then
+ local CivMenu = _MenuPool:AddSubMenu(MainMenu, 'Civ Toolbox', 'Civilian Related Menu', true)
+ CivMenu:SetMenuWidthOffset(Config.MenuWidth)
+ local CivActions = _MenuPool:AddSubMenu(CivMenu, 'Actions', '', true)
+ CivActions:SetMenuWidthOffset(Config.MenuWidth)
+ local HU = NativeUI.CreateItem('Hands Up', 'Put your hands up')
+ local HUK = NativeUI.CreateItem('Hand Up & Kneel', 'Put your hands up and kneel on the ground')
+ local Inventory = NativeUI.CreateItem('Inventory', 'Set your inventory')
+ local BAC = NativeUI.CreateItem('BAC', 'Set your BAC level')
+ local DropWeapon = NativeUI.CreateItem('Drop Weapon', 'Drop your current weapon on the ground')
+ CivActions:AddItem(HU)
+ CivActions:AddItem(HUK)
+ CivActions:AddItem(Inventory)
+ CivActions:AddItem(BAC)
+ CivActions:AddItem(DropWeapon)
+ HU.Activated = function(ParentMenu, SelectedItem)
+ local Ped = PlayerPedId()
+ if DoesEntityExist(Ped) and not HandCuffed then
+ Citizen.CreateThread(function()
+ LoadAnimation('random@mugging3')
+ if IsEntityPlayingAnim(Ped, 'random@mugging3', 'handsup_standing_base', 3) or HandCuffed then
+ ClearPedSecondaryTask(Ped)
+ SetEnableHandcuffs(Ped, false)
+ elseif not IsEntityPlayingAnim(Ped, 'random@mugging3', 'handsup_standing_base', 3) or not HandCuffed then
+ TaskPlayAnim(Ped, 'random@mugging3', 'handsup_standing_base', 8.0, -8, -1, 49, 0, 0, 0, 0)
+ SetEnableHandcuffs(Ped, true)
+ end
+ end)
+ end
+ end
+ HUK.Activated = function(ParentMenu, SelectedItem)
+ local Ped = PlayerPedId()
+ if (DoesEntityExist(Ped) and not IsEntityDead(Ped)) and not HandCuffed then
+ Citizen.CreateThread(function()
+ LoadAnimation('random@arrests')
+ if (IsEntityPlayingAnim(Ped, 'random@arrests', 'kneeling_arrest_idle', 3)) then
+ TaskPlayAnim(Ped, 'random@arrests', 'kneeling_arrest_get_up', 8.0, 1.0, -1, 128, 0, 0, 0, 0)
+ else
+ TaskPlayAnim(Ped, 'random@arrests', 'idle_2_hands_up', 8.0, 1.0, -1, 2, 0, 0, 0, 0)
+ Wait (4000)
+ TaskPlayAnim(Ped, 'random@arrests', 'kneeling_arrest_idle', 8.0, 1.0, -1, 2, 0, 0, 0, 0)
+ end
+ end)
+ end
+ end
+ Inventory.Activated = function(ParentMenu, SelectedItem)
+ local Items = KeyboardInput('Items:', 75)
+ if Items == nil or Items == '' then
+ Notify('~r~No Items Provided!')
+ return
+ end
+
+ TriggerServerEvent('SEM_InteractionMenu:InventorySet', Items)
+ Notify('~g~Inventory Set!')
+ end
+ BAC.Activated = function(ParentMenu, SelectedItem)
+ local BACLevel = KeyboardInput('BAC Level - Legal Limit: 0.08', 5)
+ if BACLevel == nil or BACLevel == '' then
+ Notify('~r~No BAC Level Provided!')
+ return
+ end
+
+ TriggerServerEvent('SEM_InteractionMenu:BACSet', tonumber(BACLevel))
+ if tonumber(BACLevel) < 0.08 then
+ Notify('~b~BAC Level Set: ~g~' .. tostring(BACLevel))
+ else
+ Notify('~b~BAC Level Set: ~r~' .. tostring(BACLevel))
+ end
+ end
+ DropWeapon.Activated = function(ParentMenu, SelectedItem)
+ local CurrentWeapon = GetSelectedPedWeapon(PlayerPedId())
+ SetCurrentPedWeapon(PlayerPedId(), 'weapon_unarmed', true)
+ SetPedDropsInventoryWeapon(GetPlayerPed(-1), CurrentWeapon, -2.0, 0.0, 0.5, 30)
+ Notify('~r~Weapon Dropped!')
+ end
+ if Config.ShowCivAdverts then
+ local CivAdverts = _MenuPool:AddSubMenu(CivMenu, 'Adverts', '', true)
+ CivAdverts:SetMenuWidthOffset(Config.MenuWidth)
+ for _, Ad in pairs(Config.CivAdverts) do
+ local Advert = NativeUI.CreateItem(Ad.name, 'Send an advert for ' .. Ad.name)
+ CivAdverts:AddItem(Advert)
+ Advert.Activated = function(ParentMenu, SelectedItem)
+ local Message = KeyboardInput('Message:', 128)
+ if Message == nil or Message == '' then
+ Notify('~r~No Advert Message Provided!')
+ return
+ end
+
+ TriggerServerEvent('SEM_InteractionMenu:Ads', Message, Ad.name, Ad.loc, Ad.file)
+ end
+ end
+ end
+ if Config.ShowCivVehicles then
+ local CivVehicles = _MenuPool:AddSubMenu(CivMenu, 'Vehicles', '', true)
+ CivVehicles:SetMenuWidthOffset(Config.MenuWidth)
+
+ for _, Vehicle in pairs(Config.CivVehicles) do
+ local CivVehicle = NativeUI.CreateItem(Vehicle.name, '')
+ CivVehicles:AddItem(CivVehicle)
+ if Config.ShowCivSpawnCode then
+ CivVehicle:RightLabel(Vehicle.spawncode)
+ end
+ CivVehicle.Activated = function(ParentMenu, SelectedItem)
+ SpawnVehicle(Vehicle.spawncode, Vehicle.name)
+ end
+ end
+ end
+ end
+
+
+
+
+
+ if VehicleRestrict() then
+ local VehicleMenu = _MenuPool:AddSubMenu(MainMenu, 'Vehicle', 'Vehicle Related Menu', true)
+ VehicleMenu:SetMenuWidthOffset(Config.MenuWidth)
+ local Seats = {-1, 0, 1, 2}
+ local Windows = {'Front', 'Rear', 'All'}
+ local Doors = {'Driver', 'Passenger', 'Rear Right', 'Rear Left', 'Hood', 'Trunk', 'All'}
+ local Engine = NativeUI.CreateItem('Toggle Engine', 'Toggle your vehicle\'s engine')
+ local ILights = NativeUI.CreateItem('Toggle Interior Light', 'Toggle your vehicle\'s interior light')
+ local Seat = NativeUI.CreateSliderItem('Change Seats', Seats, 1, 'Switch to a different seat')
+ local Window = NativeUI.CreateListItem('Windows', Windows, 1, 'Open/Close your vehicle\'s windows')
+ local Door = NativeUI.CreateListItem('Doors', Doors, 1, 'Open/Close your vehicle\'s doors')
+ local FixVeh = NativeUI.CreateItem('Repair Vehicle', 'Repair your current vehicle')
+ local CleanVeh = NativeUI.CreateItem('Clean Vehicle', 'Clean your current vehicle')
+ local DelVeh = NativeUI.CreateItem('~r~Delete Vehicle', 'Delete your current vehicle')
+ VehicleMenu:AddItem(Engine)
+ VehicleMenu:AddItem(ILights)
+ VehicleMenu:AddItem(Seat)
+ VehicleMenu:AddItem(Window)
+ VehicleMenu:AddItem(Door)
+ if Config.VehicleOptions then
+ VehicleMenu:AddItem(FixVeh)
+ VehicleMenu:AddItem(CleanVeh)
+ VehicleMenu:AddItem(DelVeh)
+ end
+ Engine.Activated = function(ParentMenu, SelectedItem)
+ local Vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
+ if Vehicle ~= nil and Vehicle ~= 0 and GetPedInVehicleSeat(Vehicle, 0) then
+ SetVehicleEngineOn(Vehicle, (not GetIsVehicleEngineRunning(Vehicle)), false, true)
+ Notify('~g~Engine Toggled!')
+ else
+ Notify('~r~You\'re not in a Vehicle!')
+ end
+ end
+ ILights.Activated = function(ParentMenu, SelectedItem)
+ local Vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
+
+ if IsPedInVehicle(PlayerPedId(), Vehicle, false) then
+ if IsVehicleInteriorLightOn(Vehicle) then
+ SetVehicleInteriorlight(Vehicle, false)
+ else
+ SetVehicleInteriorlight(Vehicle, true)
+ end
+ else
+ Notify('~r~You\'re not in a Vehicle!')
+ end
+ end
+ VehicleMenu.OnSliderChange = function(sender, item, index)
+ if item == Seat then
+ VehicleSeat = item:IndexToItem(index)
+ local Veh = GetVehiclePedIsIn(GetPlayerPed(-1),false)
+ SetPedIntoVehicle(PlayerPedId(), Veh, VehicleSeat)
+ end
+ end
+ VehicleMenu.OnListSelect = function(sender, item, index)
+ local Ped = GetPlayerPed(-1)
+ local Veh = GetVehiclePedIsIn(Ped, false)
+
+ if item == Window then
+ VehicleWindow = item:IndexToItem(index)
+ if VehicleWindow == 'Front' then
+ if IsPedInAnyVehicle(Ped, false) then
+ if (GetPedInVehicleSeat(Veh, -1) == Ped) then
+ SetEntityAsMissionEntity(Veh, true, true)
+ if (WindowFrontRolled) then
+ RollDownWindow(Veh, 0)
+ RollDownWindow(Veh, 1)
+ WindowFrontRolled = false
+ else
+ RollUpWindow(Veh, 0)
+ RollUpWindow(Veh, 1)
+ WindowFrontRolled = true
+ end
+ end
+ end
+ elseif VehicleWindow == 'Rear' then
+ if IsPedInAnyVehicle(Ped, false) then
+ if (GetPedInVehicleSeat(Veh, -1) == Ped) then
+ SetEntityAsMissionEntity(Veh, true, true)
+ if (WindowFrontRolled) then
+ RollDownWindow(Veh, 2)
+ RollDownWindow(Veh, 3)
+ WindowFrontRolled = false
+ else
+ RollUpWindow(Veh, 2)
+ RollUpWindow(Veh, 3)
+ WindowFrontRolled = true
+ end
+ end
+ end
+ elseif VehicleWindow == 'All' then
+ if IsPedInAnyVehicle(Ped, false) then
+ if (GetPedInVehicleSeat(Veh, -1) == Ped) then
+ SetEntityAsMissionEntity(Veh, true, true)
+ if (WindowFrontRolled) then
+ RollDownWindow(Veh, 0)
+ RollDownWindow(Veh, 1)
+ RollDownWindow(Veh, 2)
+ RollDownWindow(Veh, 3)
+ WindowFrontRolled = false
+ else
+ RollUpWindow(Veh, 0)
+ RollUpWindow(Veh, 1)
+ RollUpWindow(Veh, 2)
+ RollUpWindow(Veh, 3)
+ WindowFrontRolled = true
+ end
+ end
+ end
+ end
+ elseif item == Door then
+ local Doors = {'Driver', 'Passenger', 'Rear Left', 'Rear Right', 'Hood', 'Trunk', 'All'}
+ VehicleDoor = item:IndexToItem(index)
+ if VehicleDoor == 'Driver' then
+ if Veh ~= nil and Veh ~= 0 and Veh ~= 1 then
+ if GetVehicleDoorAngleRatio(Veh, 0) > 0 then
+ SetVehicleDoorShut(Veh, 0, false)
+ else
+ SetVehicleDoorOpen(Veh, 0, false, false)
+ end
+ end
+ elseif VehicleDoor == 'Passenger' then
+ if Veh ~= nil and Veh ~= 0 and Veh ~= 1 then
+ if GetVehicleDoorAngleRatio(Veh, 1) > 0 then
+ SetVehicleDoorShut(Veh, 1, false)
+ else
+ SetVehicleDoorOpen(Veh, 1, false, false)
+ end
+ end
+ elseif VehicleDoor == 'Rear Left' then
+ if Veh ~= nil and Veh ~= 0 and Veh ~= 1 then
+ if GetVehicleDoorAngleRatio(Veh, 2) > 0 then
+ SetVehicleDoorShut(Veh, 2, false)
+ else
+ SetVehicleDoorOpen(Veh, 2, false, false)
+ end
+ end
+ elseif VehicleDoor == 'Rear Right' then
+ if Veh ~= nil and Veh ~= 0 and Veh ~= 1 then
+ if GetVehicleDoorAngleRatio(Veh, 3) > 0 then
+ SetVehicleDoorShut(Veh, 3, false)
+ else
+ SetVehicleDoorOpen(Veh, 3, false, false)
+ end
+ end
+ elseif VehicleDoor == 'Hood' then
+ if Veh ~= nil and Veh ~= 0 and Veh ~= 1 then
+ if GetVehicleDoorAngleRatio(Veh, 4) > 0 then
+ SetVehicleDoorShut(Veh, 4, false)
+ else
+ SetVehicleDoorOpen(Veh, 4, false, false)
+ end
+ end
+ elseif VehicleDoor == 'Trunk' then
+ if Veh ~= nil and Veh ~= 0 and Veh ~= 1 then
+ if GetVehicleDoorAngleRatio(Veh, 5) > 0 then
+ SetVehicleDoorShut(Veh, 5, false)
+ else
+ SetVehicleDoorOpen(Veh, 5, false, false)
+ end
+ end
+ elseif VehicleDoor == 'All' then
+ if Veh ~= nil and Veh ~= 0 and Veh ~= 1 then
+ if GetVehicleDoorAngleRatio(Veh, 0) > 0 then
+ SetVehicleDoorShut(Veh, 0, false)
+ SetVehicleDoorShut(Veh, 1, false)
+ SetVehicleDoorShut(Veh, 2, false)
+ SetVehicleDoorShut(Veh, 3, false)
+ SetVehicleDoorShut(Veh, 4, false)
+ SetVehicleDoorShut(Veh, 5, false)
+ else
+ SetVehicleDoorOpen(Veh, 0, false, false)
+ SetVehicleDoorOpen(Veh, 1, false, false)
+ SetVehicleDoorOpen(Veh, 2, false, false)
+ SetVehicleDoorOpen(Veh, 3, false, false)
+ SetVehicleDoorOpen(Veh, 4, false, false)
+ SetVehicleDoorOpen(Veh, 5, false, false)
+ end
+ end
+ end
+ end
+ end
+ FixVeh.Activated = function(ParentMenu, SelectedItem)
+ local Vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
+ if Vehicle ~= nil and Vehicle ~= 0 then
+ SetVehicleEngineHealth(Vehicle, 100)
+ SetVehicleFixed(Vehicle)
+ Notify('~g~Vehicle Repaired!')
+ else
+ Notify('~r~You\'re not in a Vehicle!')
+ end
+
+ end
+ CleanVeh.Activated = function(ParentMenu, SelectedItem)
+ local Vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
+ if Vehicle ~= nil and Vehicle ~= 0 then
+ SetVehicleDirtLevel(Vehicle, 0)
+ Notify('~g~Vehicle Cleaned!')
+ else
+ Notify('~r~You\'re not in a Vehicle!')
+ end
+ end
+ DelVeh.Activated = function(ParentMenu, SelectedItem)
+ if (IsPedSittingInAnyVehicle(PlayerPedId())) then
+ local Vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
+
+ if (GetPedInVehicleSeat(Vehicle, -1) == PlayerPedId()) then
+ SetEntityAsMissionEntity(Vehicle, true, true)
+ DeleteVehicle(Vehicle)
+
+ if (DoesEntityExist(Vehicle)) then
+ Notify('~o~Unable to delete vehicle, try again.')
+ else
+ Notify('~r~Vehicle Deleted!')
+ end
+ else
+ Notify('~r~You must be in the driver\'s seat!')
+ end
+ else
+ Notify('~r~You\'re not in a Vehicle!')
+ end
+ end
+ end
+
+
+
+
+
+ if EmoteRestrict() then
+ local EmotesList = {}
+ for _, Emote in pairs(Config.EmotesList) do
+ table.insert(EmotesList, Emote.name)
+ end
+
+ local EmotesMenu = NativeUI.CreateListItem('Emotes', EmotesList, 1, 'General RP Emotes')
+ MainMenu:AddItem(EmotesMenu)
+
+ MainMenu.OnListSelect = function(sender, item, index)
+ if item == EmotesMenu then
+ for _, Emote in pairs(Config.EmotesList) do
+ if Emote.name == item:IndexToItem(index) then
+ PlayEmote(Emote.emote, Emote.name)
+ end
+ end
+ end
+ end
+ end
+
+
+
+ _MenuPool:RefreshIndex()
+end
+
+
+
+Citizen.CreateThread(function()
+ while true do
+ Citizen.Wait(0)
+
+ _MenuPool:ProcessMenus()
+ _MenuPool:ControlDisablingEnabled(false)
+ _MenuPool:MouseControlsEnabled(false)
+
+ if IsControlJustPressed(1, Config.MenuButton) and GetLastInputMethod(2) then
+ if not menuOpen then
+ Menu()
+ MainMenu:Visible(true)
+ else
+ _MenuPool:CloseAllMenus()
+ end
+ end
+ end
+end)
+
+
+
+RegisterCommand(Config.Command, function(source, args, rawCommands)
+ if Config.OpenMenu == 1 then
+ Menu()
+ MainMenu:Visible(true)
+ end
+end)
+
+Citizen.CreateThread(function()
+ if Config.OpenMenu == 1 then
+ TriggerEvent('chat:addSuggestion', '/' .. Config.Command, 'Used to open SEM_InteractionMenu')
+ end
+end)
diff --git a/resources/Interaction-Menu/server.lua b/resources/Interaction-Menu/server.lua
new file mode 100644
index 000000000..abb055a30
--- /dev/null
+++ b/resources/Interaction-Menu/server.lua
@@ -0,0 +1,246 @@
+--[[
+───────────────────────────────────────────────────────────────
+
+ SEM_InteractionMenu (server.lua) - Created by Scott M
+ Current Version: v1.7.1 (Sep 2021)
+
+ Support: https://semdevelopment.com/discord
+
+ !!! Change vaules in the 'config.lua' !!!
+ DO NOT EDIT THIS IF YOU DON'T KNOW WHAT YOU ARE DOING
+
+───────────────────────────────────────────────────────────────
+]]
+
+
+
+RegisterServerEvent('SEM_InteractionMenu:GlobalChat')
+AddEventHandler('SEM_InteractionMenu:GlobalChat', function(Color, Prefix, Message)
+ TriggerClientEvent('chatMessage', -1, Prefix, Color, Message)
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:CuffNear')
+AddEventHandler('SEM_InteractionMenu:CuffNear', function(ID)
+ if ID == -1 or ID == '-1' then
+ if source ~= '' then
+ print('^1[#' .. source .. '] ' .. GetPlayerName(source) .. ' - attempted to cuff all players^7')
+ DropPlayer(source, '\n[SEM_InteractionMenu] Attempting to cuff all players')
+ else
+ print('^1Someone attempted to cuff all players^7')
+ end
+
+ return
+ end
+
+ if ID ~= false then
+ TriggerClientEvent('SEM_InteractionMenu:Cuff', ID)
+ end
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:DragNear')
+AddEventHandler('SEM_InteractionMenu:DragNear', function(ID)
+ if ID == -1 or ID == '-1' then
+ if source ~= '' then
+ print('^1[#' .. source .. '] ' .. GetPlayerName(source) .. ' - attempted to drag all players^7')
+ DropPlayer(source, '\n[SEM_InteractionMenu] Attempting to drag all players')
+ else
+ print('^1Someone attempted to drag all players^7')
+ end
+
+ return
+ end
+
+ if ID ~= false and ID ~= source then
+ TriggerClientEvent('SEM_InteractionMenu:Drag', ID, source)
+ end
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:SeatNear')
+AddEventHandler('SEM_InteractionMenu:SeatNear', function(ID, Vehicle)
+ TriggerClientEvent('SEM_InteractionMenu:Seat', ID, Vehicle)
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:UnseatNear')
+AddEventHandler('SEM_InteractionMenu:UnseatNear', function(ID, Vehicle)
+ TriggerClientEvent('SEM_InteractionMenu:Unseat', ID, Vehicle)
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:Jail')
+AddEventHandler('SEM_InteractionMenu:Jail', function(ID, Time)
+ if ID == -1 or ID == '-1' then
+ if source ~= '' then
+ print('^1[#' .. source .. '] ' .. GetPlayerName(source) .. ' - attempted to jail all players^7')
+ DropPlayer(source, '\n[SEM_InteractionMenu] Attempting to jail all players')
+ else
+ print('^1Someone attempted to jail all players^7')
+ end
+
+ return
+ end
+
+ TriggerClientEvent('SEM_InteractionMenu:JailPlayer', ID, Time)
+ TriggerClientEvent('chatMessage', -1, 'Judge', {86, 96, 252}, GetPlayerName(ID) .. ' has been Jailed for ' .. Time .. ' months(s)')
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:Unjail')
+AddEventHandler('SEM_InteractionMenu:Unjail', function(ID)
+ TriggerClientEvent('SEM_InteractionMenu:UnjailPlayer', ID)
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:Backup')
+AddEventHandler('SEM_InteractionMenu:Backup', function(Code, StreetName, Coords)
+ TriggerClientEvent('SEM_InteractionMenu:CallBackup', -1, Code, StreetName, Coords)
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:Ads')
+AddEventHandler('SEM_InteractionMenu:Ads', function(Text, Name, Loc, File)
+ TriggerClientEvent('SEM_InteractionMenu:SyncAds', -1, Text, Name, Loc, File, source)
+end)
+
+BACList = {}
+RegisterServerEvent('SEM_InteractionMenu:BACSet')
+AddEventHandler('SEM_InteractionMenu:BACSet', function(BACLevel)
+ BACList[source] = BACLevel
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:BACTest')
+AddEventHandler('SEM_InteractionMenu:BACTest', function(ID)
+ local BACLevel = BACList[ID]
+ TriggerClientEvent('SEM_InteractionMenu:BACResult', source, BACLevel)
+end)
+
+Inventories = {}
+RegisterServerEvent('SEM_InteractionMenu:InventorySet')
+AddEventHandler('SEM_InteractionMenu:InventorySet', function(Items)
+ Inventories[source] = Items
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:InventorySearch')
+AddEventHandler('SEM_InteractionMenu:InventorySearch', function(ID)
+ local Inventory = Inventories[ID]
+
+ TriggerClientEvent('SEM_InteractionMenu:InventoryResult', source, Inventory)
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:Hospitalize')
+AddEventHandler('SEM_InteractionMenu:Hospitalize', function(ID, Time, Location)
+ if ID == -1 or ID == '-1' then
+ if source ~= '' then
+ print('^1[#' .. source .. '] ' .. GetPlayerName(source) .. ' - attempted to hospitalize all players^7')
+ DropPlayer(source, '\n[SEM_InteractionMenu] Attempting to hospitalize all players')
+ else
+ print('^1Someone attempted to hospitalize all players^7')
+ end
+
+ return
+ end
+
+ TriggerClientEvent('SEM_InteractionMenu:HospitalizePlayer', ID, Time, Location)
+ TriggerClientEvent('chatMessage', -1, 'Doctor', {86, 96, 252}, GetPlayerName(ID) .. ' has been Hospitalized for ' .. Time .. ' months(s)')
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:Unhospitalize')
+AddEventHandler('SEM_InteractionMenu:Unhospitalize', function(ID)
+ TriggerClientEvent('SEM_InteractionMenu:UnhospitalizePlayer', ID)
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:LEOPerms')
+AddEventHandler('SEM_InteractionMenu:LEOPerms', function()
+ if IsPlayerAceAllowed(source, 'sem_intmenu.leo') then
+ TriggerClientEvent('SEM_InteractionMenu:LEOPermsResult', source, true)
+ else
+ TriggerClientEvent('SEM_InteractionMenu:LEOPermsResult', source, false)
+ end
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:FirePerms')
+AddEventHandler('SEM_InteractionMenu:FirePerms', function()
+ if IsPlayerAceAllowed(source, 'sem_intmenu.fire') then
+ TriggerClientEvent('SEM_InteractionMenu:FirePermsResult', source, true)
+ else
+ TriggerClientEvent('SEM_InteractionMenu:FirePermsResult', source, false)
+ end
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:UnjailPerms')
+AddEventHandler('SEM_InteractionMenu:UnjailPerms', function()
+ if IsPlayerAceAllowed(source, 'sem_intmenu.unjail') then
+ TriggerClientEvent('SEM_InteractionMenu:UnjailPermsResult', source, true)
+ else
+ TriggerClientEvent('SEM_InteractionMenu:UnjailPermsResult', source, false)
+ end
+end)
+
+RegisterServerEvent('SEM_InteractionMenu:UnhospitalPerms')
+AddEventHandler('SEM_InteractionMenu:UnhospitalPerms', function()
+ if IsPlayerAceAllowed(source, 'sem_intmenu.unhospital') then
+ TriggerClientEvent('SEM_InteractionMenu:UnhospitalPermsResult', source, true)
+ else
+ TriggerClientEvent('SEM_InteractionMenu:UnhospitalPermsResult', source, false)
+ end
+end)
+
+
+local resourceName =
+[[^3
+ _____ ______ _____ _____
+ / ____| | ___| | \ / |
+ | (___ | |___ | |\ \ / /| |
+ \___ \ | ___| | | \ \/ / | |
+ ____) | | |___ | | \ / | |
+ \_____/ |______| |__| \__/ |__|^7
+ InteractionMenu
+ Created By Scott M
+]]
+
+Citizen.CreateThread(function()
+ local currentVersion = GetResourceMetadata(GetCurrentResourceName(), 'version', 0)
+
+ function VersionCheckHTTPRequest()
+ PerformHttpRequest('https://semdevelopment.com/releases/interactionmenu/info/version.json', VersionCheck, 'GET')
+ end
+
+ function VersionCheck(err, response, headers)
+ Citizen.Wait(3000)
+ if err == 200 then
+ local data = json.decode(response)
+
+ if Config.VersionChecker == 0 then
+ print(resourceName)
+ end
+
+ if currentVersion ~= data.NewestVersion then
+ if Config.VersionChecker == 0 then
+ print('\n ^1SEM_InteractionMenu is outdated!^7')
+ print(' Latest Version: ^2' .. data.NewestVersion .. '^7')
+ print(' Your Version: ^1' .. currentVersion .. '^7')
+ print(' Please download the leastest version from ^5' .. data.DownloadLocation .. '^7')
+
+ if data.Changes ~= '' then
+ print('\n ^5Changes: ^7' .. data.Changes)
+ end
+ elseif Config.VersionChecker == 1 then
+ print('\n^1SEM_InteractionMenu is outdated!^7')
+ print('Latest Version: ^2' .. data.NewestVersion .. '^7')
+ print('Please download the leastest version from ^5' .. data.DownloadLocation .. '^7\n')
+ end
+ else
+ print('\n ^2SEM_InteractionMenu is up to date!^7')
+ end
+
+ print('\n')
+ else
+ print('^1SEM_InteractionMenu Version Check Failed!^7')
+ end
+
+ SetTimeout(60000000, VersionCheckHTTPRequest)
+ end
+
+ if Config.VersionChecker ~= 2 then
+ if currentVersion then
+ VersionCheckHTTPRequest()
+ else
+ print('^1SEM_InteractionMenu Version Check Failed!^7')
+ end
+ end
+end)
diff --git a/resources/Interaction-Menu/stream/char_floyd.ytd b/resources/Interaction-Menu/stream/char_floyd.ytd
new file mode 100644
index 000000000..68efafd77
--- /dev/null
+++ b/resources/Interaction-Menu/stream/char_floyd.ytd
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3f01c0e21d2134a67772d132e247918a3e494810ea64f939e108b7067eb7b165
+size 260166
diff --git a/resources/Timetrials/scores.txt b/resources/Timetrials/scores.txt
index 55baa5dbd..28f9faada 100644
--- a/resources/Timetrials/scores.txt
+++ b/resources/Timetrials/scores.txt
@@ -1 +1 @@
-{"Airport Drag Race":{"NULL":{"player":"iwan.ralphs","car":"NULL","time":7030}},"Race | BCSO Training Course":{"NULL":{"player":"ThatGuyJacobee","car":"NULL","time":100457},"2013 Dodge Charger":{"player":"vJack","car":"2013 Dodge Charger","time":94246},"Neon":{"player":"ThunderBird","car":"Neon","time":105527},"Schafter V12 (Armored)":{"player":"Bulvederis","car":"Schafter V12 (Armored)","time":53363},"2016 Dodge Ram":{"player":"vJack","car":"2016 Dodge Ram","time":119099},"Nissan Skyline GTR":{"player":"ThatGuyJacobee","car":"Nissan Skyline GTR","time":105983},"Mercedes AMG GTS":{"player":"vJack","car":"Mercedes AMG GTS","time":78151}},"Lakeside Loop":{"NULL":{"player":"DR*KINGPORNHUB","car":"NULL","time":206147}},"Race | Sandy Airfield":{"NULL":{"time":4625,"car":"NULL","player":"C-197 | FP-410 | Tristan M. | Deputy I | Probi. FF"},"BMW M5 Plus":{"player":"King Rodriguez","car":"BMW M5 Plus","time":18019},"Neon":{"player":"ThunderBird","car":"Neon","time":28815},"Toyota Sienna 2021":{"player":"Max Rodriguez","car":"Toyota Sienna 2021","time":34685},"Audi S3 2015":{"player":"King Rodriguez","car":"Audi S3 2015","time":25742},"Jeep TrackHawk 2018":{"player":"King Rodriguez","car":"Jeep TrackHawk 2018","time":22887},"Dodge Charger 2014":{"player":"C-197 | FP-410 | Tristan M. | Deputy I | Probi. FF","car":"Dodge Charger 2014","time":202399},"Verlierer":{"player":"kiyin","car":"Verlierer","time":31698},"2016 Ford Explorer":{"player":"King Rodriguez","car":"2016 Ford Explorer","time":26526},"Mini JCW 2020":{"player":"King Rodriguez","car":"Mini JCW 2020","time":29879},"2014 Dodge Charger":{"player":"King Rodriguez","car":"2014 Dodge Charger","time":29132},"BR8":{"player":"C-200 | Noki | Deputy 1 | CIV","car":"BR8","time":25853},"GMC Sierra Singlecab 2006":{"player":"herediaaldo4","car":"GMC Sierra Singlecab 2006","time":34750},"Nissan Skyline GTR":{"player":"ThatGuyJacobee","car":"Nissan Skyline GTR","time":29921},"Chevy Silverado 1500 4dr Cab 2006":{"player":"herediaaldo4","car":"Chevy Silverado 1500 4dr Cab 2006","time":29263},"Nero":{"player":"ThunderBird","car":"Nero","time":34210},"Mercedes AMG GTS":{"player":"vJack","car":"Mercedes AMG GTS","time":19029},"Dick Car":{"player":"C-197 | FP-410 | Tristan M. | Deputy I | Probi. FF","car":"Dick Car","time":23469},"Formula 1":{"player":"vJack","car":"Formula 1","time":15914},"Ferrari 458":{"player":"Woltage.2","car":"Ferrari 458","time":25352},"BMW i8":{"player":"King Rodriguez","car":"BMW i8","time":24743},"Corvette C7":{"player":"shrekislove","car":"Corvette C7","time":31909},"Jeep Grand Cherokee TrackhawkPD 2018":{"time":36165,"car":"Jeep Grand Cherokee TrackhawkPD 2018","player":"C-197 | FP-410 | Tristan M. | Deputy I | Probi. FF"},"Scramjet":{"player":"C-199|T.Oneil|Deputy I","car":"Scramjet","time":8264},"F-22A":{"player":"Yalaina-DDR8","car":"F-22A","time":90697},"Chevy Camaro20":{"player":"Max Rodriguez","car":"Chevy Camaro20","time":32202},"Itali GTO":{"player":"ThunderBird","car":"Itali GTO","time":20103},"Projen-C Sports":{"time":93333,"car":"Projen-C Sports","player":"C-200 | Noki | Deputy 1 | CIV"},"Bugatti Chiron 2017":{"player":"King Rodriguez","car":"Bugatti Chiron 2017","time":22371},"EGRP Sheriff PD":{"player":"C-197 | FP-410 | Tristan M. | Deputy I | Probi. FF","car":"EGRP Sheriff PD","time":32983},"Kawasaki Ninja ZX10R":{"time":3621,"car":"Kawasaki Ninja ZX10R","player":"C-200 | Noki | Deputy 1 | CIV"},"Dodge Ram 2dr 1500 srt 2010":{"player":"Max Rodriguez ","car":"Dodge Ram 2dr 1500 srt 2010","time":21999},"School Bus":{"time":81320,"car":"School Bus","player":"227 | Adam | Senior Officer"},"Chevrolet Silverado 2005 2dr":{"player":"herediaaldo4","car":"Chevrolet Silverado 2005 2dr","time":26183},"Yamaha R6":{"player":"ThatGuyJacobee","car":"Yamaha R6","time":28188},"Space Docker":{"player":"DyslexicStoner240.","car":"Space Docker","time":29122},"Cougar MRAP":{"player":"C-197 | FP-410 | Tristan M. | Deputy I | Probi. FF","car":"Cougar MRAP","time":51309},"Dodge Challenger srt 2020 ":{"player":"herediaaldo4","car":"Dodge Challenger srt 2020 ","time":22940},"Dodge Charger 2018tr":{"player":"ThunderBird","car":"Dodge Charger 2018tr","time":26779},"Ford Raptor F-150":{"player":"King Rodriguez","car":"Ford Raptor F-150","time":28515},"Harley Davidson":{"player":"Max Rodriguez","car":"Harley Davidson","time":34914},"Oppressor":{"player":"C-200 | Noki | Deputy 1 | CIV","car":"Oppressor","time":19491}},"BCSO Training Course":{"NULL":{"player":"ThatGuyJacobee","car":"NULL","time":26915},"Jester":{"player":"michael82","car":"Jester","time":37835}},"North GP":{"NULL":{"player":"vJack","car":"NULL","time":191650},"Baller":{"player":"dcapone00","car":"Baller","time":410118},"Neon":{"player":"ThunderBird","car":"Neon","time":354856}},"Airport Circuit":{"NULL":{"player":"ThatGuyJacobee","car":"NULL","time":22916},"P-996 LAZER":{"player":"ThatGuyJacobee","car":"P-996 LAZER","time":59216},"Neon":{"player":"ThunderBird","car":"Neon","time":92652}},"Race | Highway Sprint":{"NULL":{"player":"Travis O'Neil","car":"NULL","time":27159},"Ferrari 488s":{"player":"shrekislove","car":"Ferrari 488s","time":188921},"Lamborghini Aventador AVJ":{"player":"Kaleb","car":"Lamborghini Aventador AVJ","time":240744},"Scramjet":{"player":"Travis O'Neil","car":"Scramjet","time":200543},"Deveste Eight":{"player":"jb3794339","car":"Deveste Eight","time":181173},"Ferrari 458":{"player":"ThatGuyJacobee","car":"Ferrari 458","time":138033}},"Cannonball Run":{"NULL":{"player":"ThatGuyJacobee","car":"NULL","time":81298}},"Race | Airport Circuit":{"Ferrari 458":{"player":"ThatGuyJacobee","car":"Ferrari 458","time":69880},"Formula 1":{"player":"vJack","car":"Formula 1","time":42751},"Nissan Skyline GTR":{"player":"ThatGuyJacobee","car":"Nissan Skyline GTR","time":83978}},"Race | Observatory Loop":{"Ford F-150 Lightning 2022":{"player":"ThatGuyJacobee","car":"Ford F-150 Lightning 2022","time":68440},"2013 Dodge Charger":{"player":"vJack","car":"2013 Dodge Charger","time":64004},"Porsche 911 GT3RS":{"player":"[YJ-18] Sinapsey","car":"Porsche 911 GT3RS","time":106410},"Mercedes AMG GTS":{"player":"vJack","car":"Mercedes AMG GTS","time":56747},"Gauntlet Classic Custom":{"player":"[C-291][GCF-34][MS-13] K. Lee","car":"Gauntlet Classic Custom","time":76765},"Formula 1":{"player":"ThatGuyJacobee","car":"Formula 1","time":54744},"NULL":{"player":"[YJ-18] Sinapsey","car":"NULL","time":55388},"BMW M5 Plus":{"player":"[EGRP-02]King Rodriguez","car":"BMW M5 Plus","time":70752},"Nissan Skyline GTR":{"player":"[C-291][GCF-34][MS-13] K. Lee","car":"Nissan Skyline GTR","time":67881},"BMW M5":{"player":"[C-291][GCF-34][MS-13] K. Lee","car":"BMW M5","time":81837},"Mazda Miata":{"player":"[C-291][GCF-34][MS-13] K. Lee","car":"Mazda Miata","time":79814}},"Race | Hillside Loop":{"Bronco Wildtrak 2021":{"player":"ThatGuyJacobee","car":"Bronco Wildtrak 2021","time":210714},"Gauntlet Classic Custom":{"player":"[C-291][GCF-34][MS-13] K. Lee","car":"Gauntlet Classic Custom","time":230432},"BMW M8 Widebody":{"player":"[C-291][GCF-34][MS-13] K. Lee","car":"BMW M8 Widebody","time":195442}},"Hollywood Hills":{"NULL":{"player":"Kryplos125","car":"NULL","time":120053}},"Race | Airport Drag":{"NULL":{"player":"B. LAO","car":"NULL","time":12630},"BMW M5 Plus":{"player":"King Rodriguez","car":"BMW M5 Plus","time":8652},"Nissan Skyline GTR":{"player":"ThatGuyJacobee","car":"Nissan Skyline GTR","time":9693},"Formula 1":{"player":"King Rodriguez","car":"Formula 1","time":7629},"2010 Chevy Tahoe":{"player":"King Rodriguez","car":"2010 Chevy Tahoe","time":12821},"Police Corvette 2019":{"player":"Woltage.2","car":"Police Corvette 2019","time":14484}},"Race | Timetrial Event - 04/04/21":{"Gauntlet Classic Custom":{"player":"[C-291][GCF-34][MS-13] K. Lee","car":"Gauntlet Classic Custom","time":191695},"Chevrolet Silverado 1980":{"player":"King Rodriguez","car":"Chevrolet Silverado 1980","time":156244},"Ford Velociraptor 6x6":{"player":"ThatGuyJacobee","car":"Ford Velociraptor 6x6","time":132814}},"Highway Sprint":{"NULL":{"player":"vJack","car":"NULL","time":93300}},"North Rallycross ":{"Neon":{"player":"ThunderBird","car":"Neon","time":351612}},"Observatory Loop":{"NULL":{"player":"ThatGuyJacobee","car":"NULL","time":34126}},"Race | Airport Drag Race":{"NULL":{"player":"DR-KingRodriguez","car":"NULL","time":9270}},"Race | Lakeside Loop":{"Sheriff Cruiser":{"player":"Ole Stinky","car":"Sheriff Cruiser","time":153384},"Adder":{"player":"Oli","car":"Adder","time":30689},"Bifta":{"time":248420,"car":"Bifta","player":"Who Dat"},"Ferrari 458":{"player":"ThatGuyJacobee","car":"Ferrari 458","time":177461},"SNOWMOBILE 2020":{"player":"[C-146] E. Cartman","car":"SNOWMOBILE 2020","time":107015},"Kawasaki Ninja ZX10R":{"time":28696,"car":"Kawasaki Ninja ZX10R","player":"C-200 | Noki | Deputy 1 | CIV"},"Ford Crown Vic 2011":{"player":"AnySpiderBat","car":"Ford Crown Vic 2011","time":231931},"EGRP Staff Buggy":{"player":"[EGRP-02]King Rodriguez","car":"EGRP Staff Buggy","time":43710},"NULL":{"player":"ThatGuyJacobee","car":"NULL","time":196803},"Ford Explorer 2020":{"player":"shrekislove","car":"Ford Explorer 2020","time":260276}},"Race | Cannonball Run":{"Scramjet":{"player":"C-199|T.Oneil|Deputy I","car":"Scramjet","time":66921},"2013 Dodge Charger":{"player":"vJack","car":"2013 Dodge Charger","time":263368}},"Race | Hollywood Hills":{"NULL":{"player":"ThatGuyJacobee","car":"NULL","time":102048},"Ruiner 2000":{"player":"Travis O'Neil","car":"Ruiner 2000","time":140708},"Mercedes AMG GTS":{"player":"vJack","car":"Mercedes AMG GTS","time":85823},"Ford F-150 Lightning 2022":{"player":"ThatGuyJacobee","car":"Ford F-150 Lightning 2022","time":105278},"Audi R8 V10":{"player":"ThatGuyJacobee","car":"Audi R8 V10","time":100677}},"Sandy Airfield":{"RE-7B":{"player":"*ZbyniU*","car":"RE-7B","time":28456},"FH-1 Hunter":{"player":"*ZbyniU*","car":"FH-1 Hunter","time":36289},"Maverick":{"player":"vJack","car":"Maverick","time":29165},"NULL":{"player":"ThatGuyJacobee","car":"NULL","time":5607},"Neon":{"player":"ThunderBird","car":"Neon","time":30312},"Vigilante":{"player":"*ZbyniU*","car":"Vigilante","time":6172},"Jester":{"player":"michael82","car":"Jester","time":47982},"BMX":{"player":"vJack","car":"BMX","time":21014},"Oppressor":{"player":"michael82","car":"Oppressor","time":21360}},"Race | North GP":{"SNOWMOBILE 2020":{"player":"ThatGuyJacobee","car":"SNOWMOBILE 2020","time":387242},"BMW M5":{"player":"Stormzy","car":"BMW M5","time":115460},"Mercedes AMG GTS":{"player":"Srgt Splooje","car":"Mercedes AMG GTS","time":91546},"NULL":{"player":"SOGGYBEAN","car":"NULL","time":42917},"Windsor Drop":{"player":"[C-81][GCF-145] R. Freeman","car":"Windsor Drop","time":66673},"2014 Pierce prescue":{"player":"Klimek07","car":"2014 Pierce prescue","time":83300}}}
\ No newline at end of file
+{"Race | Hillside Loop":{"Bronco Wildtrak 2021":{"time":210714,"player":"ThatGuyJacobee","car":"Bronco Wildtrak 2021"},"BMW M8 Widebody":{"time":195442,"player":"[C-291][GCF-34][MS-13] K. Lee","car":"BMW M8 Widebody"},"Gauntlet Classic Custom":{"time":230432,"player":"[C-291][GCF-34][MS-13] K. Lee","car":"Gauntlet Classic Custom"}},"Lakeside Loop":{"NULL":{"time":206147,"player":"DR*KINGPORNHUB","car":"NULL"}},"Race | Highway Sprint":{"Deveste Eight":{"time":181173,"player":"jb3794339","car":"Deveste Eight"},"Ferrari 488s":{"time":188921,"player":"shrekislove","car":"Ferrari 488s"},"Scramjet":{"time":200543,"player":"Travis O'Neil","car":"Scramjet"},"Formula 1":{"car":"Formula 1","player":"shrekislove","time":115451},"Ferrari 458":{"time":138033,"player":"ThatGuyJacobee","car":"Ferrari 458"},"Lamborghini Aventador AVJ":{"time":240744,"player":"Kaleb","car":"Lamborghini Aventador AVJ"},"NULL":{"time":27159,"player":"Travis O'Neil","car":"NULL"}},"Race | North GP":{"Mercedes AMG GTS":{"time":91546,"player":"Srgt Splooje","car":"Mercedes AMG GTS"},"BMW M5":{"time":115460,"player":"Stormzy","car":"BMW M5"},"Windsor Drop":{"time":66673,"player":"[C-81][GCF-145] R. Freeman","car":"Windsor Drop"},"2014 Pierce prescue":{"time":83300,"player":"Klimek07","car":"2014 Pierce prescue"},"NULL":{"time":42917,"player":"SOGGYBEAN","car":"NULL"},"SNOWMOBILE 2020":{"time":387242,"player":"ThatGuyJacobee","car":"SNOWMOBILE 2020"}},"Airport Drag Race":{"NULL":{"time":7030,"player":"iwan.ralphs","car":"NULL"}},"Race | Cannonball Run":{"Scramjet":{"time":66921,"player":"C-199|T.Oneil|Deputy I","car":"Scramjet"},"2013 Dodge Charger":{"time":263368,"player":"vJack","car":"2013 Dodge Charger"}},"Race | Hollywood Hills":{"Mercedes AMG GTS":{"time":85823,"player":"vJack","car":"Mercedes AMG GTS"},"Ford F-150 Lightning 2022":{"time":105278,"player":"ThatGuyJacobee","car":"Ford F-150 Lightning 2022"},"Audi R8 V10":{"time":100677,"player":"ThatGuyJacobee","car":"Audi R8 V10"},"NULL":{"time":102048,"player":"ThatGuyJacobee","car":"NULL"},"Ruiner 2000":{"time":140708,"player":"Travis O'Neil","car":"Ruiner 2000"}},"Race | Lakeside Loop":{"Bifta":{"car":"Bifta","player":"Who Dat","time":248420},"EGRP Staff Buggy":{"time":43710,"player":"[EGRP-02]King Rodriguez","car":"EGRP Staff Buggy"},"BMW S 1000 RR":{"time":21701,"player":"C-200 | Noki | Deputy 1 | CIV","car":"BMW S 1000 RR"},"Kawasaki Ninja ZX10R":{"car":"Kawasaki Ninja ZX10R","player":"C-200 | Noki | Deputy 1 | CIV","time":28696},"Adder":{"time":30689,"player":"Oli","car":"Adder"},"NULL":{"time":196803,"player":"ThatGuyJacobee","car":"NULL"},"Sheriff Cruiser":{"time":153384,"player":"Ole Stinky","car":"Sheriff Cruiser"},"Ford Crown Vic 2011":{"time":231931,"player":"AnySpiderBat","car":"Ford Crown Vic 2011"},"Ferrari 458":{"time":177461,"player":"ThatGuyJacobee","car":"Ferrari 458"},"Ford Explorer 2020":{"time":260276,"player":"shrekislove","car":"Ford Explorer 2020"},"SNOWMOBILE 2020":{"time":107015,"player":"[C-146] E. Cartman","car":"SNOWMOBILE 2020"}},"North GP":{"Neon":{"time":354856,"player":"ThunderBird","car":"Neon"},"NULL":{"time":191650,"player":"vJack","car":"NULL"},"Baller":{"time":410118,"player":"dcapone00","car":"Baller"}},"Race | Airport Circuit":{"Formula 1":{"time":42751,"player":"vJack","car":"Formula 1"},"Ferrari 458":{"time":69880,"player":"ThatGuyJacobee","car":"Ferrari 458"},"Nissan Skyline GTR":{"time":83978,"player":"ThatGuyJacobee","car":"Nissan Skyline GTR"}},"BCSO Training Course":{"NULL":{"time":26915,"player":"ThatGuyJacobee","car":"NULL"},"Jester":{"time":37835,"player":"michael82","car":"Jester"}},"Race | BCSO Training Course":{"Schafter V12 (Armored)":{"time":53363,"player":"Bulvederis","car":"Schafter V12 (Armored)"},"2013 Dodge Charger":{"time":94246,"player":"vJack","car":"2013 Dodge Charger"},"Mercedes AMG GTS":{"time":78151,"player":"vJack","car":"Mercedes AMG GTS"},"Nissan Skyline GTR":{"time":105983,"player":"ThatGuyJacobee","car":"Nissan Skyline GTR"},"2016 Dodge Ram":{"time":119099,"player":"vJack","car":"2016 Dodge Ram"},"NULL":{"time":100457,"player":"ThatGuyJacobee","car":"NULL"},"Neon":{"time":105527,"player":"ThunderBird","car":"Neon"}},"Race | Timetrial Event - 04/04/21":{"Ford Velociraptor 6x6":{"time":132814,"player":"ThatGuyJacobee","car":"Ford Velociraptor 6x6"},"Gauntlet Classic Custom":{"time":191695,"player":"[C-291][GCF-34][MS-13] K. Lee","car":"Gauntlet Classic Custom"},"Chevrolet Silverado 1980":{"time":156244,"player":"King Rodriguez","car":"Chevrolet Silverado 1980"}},"Race | Sandy Airfield":{"Chevy Silverado 1500 4dr Cab 2006":{"time":29263,"player":"herediaaldo4","car":"Chevy Silverado 1500 4dr Cab 2006"},"EGRP Sheriff PD":{"time":32983,"player":"C-197 | FP-410 | Tristan M. | Deputy I | Probi. FF","car":"EGRP Sheriff PD"},"Formula 1":{"time":15914,"player":"vJack","car":"Formula 1"},"Dick Car":{"time":23469,"player":"C-197 | FP-410 | Tristan M. | Deputy I | Probi. FF","car":"Dick Car"},"Scramjet":{"time":8264,"player":"C-199|T.Oneil|Deputy I","car":"Scramjet"},"BMW M5 Plus":{"time":18019,"player":"King Rodriguez","car":"BMW M5 Plus"},"2014 Dodge Charger":{"time":29132,"player":"King Rodriguez","car":"2014 Dodge Charger"},"Dodge Charger 2018tr":{"time":26779,"player":"ThunderBird","car":"Dodge Charger 2018tr"},"BMW i8":{"time":24743,"player":"King Rodriguez","car":"BMW i8"},"Ford Raptor F-150":{"time":28515,"player":"King Rodriguez","car":"Ford Raptor F-150"},"Cliffhanger":{"car":"Cliffhanger","player":"Zoneil121","time":45601},"Audi S3 2015":{"time":25742,"player":"King Rodriguez","car":"Audi S3 2015"},"GMC Sierra Singlecab 2006":{"time":34750,"player":"herediaaldo4","car":"GMC Sierra Singlecab 2006"},"Chevrolet Silverado 2005 2dr":{"time":26183,"player":"herediaaldo4","car":"Chevrolet Silverado 2005 2dr"},"Toyota Sienna 2021":{"time":34685,"player":"Max Rodriguez","car":"Toyota Sienna 2021"},"BMW S 1000 RR":{"time":3221,"player":"C-200 | Noki | Deputy 1 | CIV","car":"BMW S 1000 RR"},"Cougar MRAP":{"time":51309,"player":"C-197 | FP-410 | Tristan M. | Deputy I | Probi. FF","car":"Cougar MRAP"},"Harley Davidson":{"time":34914,"player":"Max Rodriguez","car":"Harley Davidson"},"Oppressor":{"time":19491,"player":"C-200 | Noki | Deputy 1 | CIV","car":"Oppressor"},"F-22A":{"time":90697,"player":"Yalaina-DDR8","car":"F-22A"},"Yamaha R6":{"time":28188,"player":"ThatGuyJacobee","car":"Yamaha R6"},"Space Docker":{"time":29122,"player":"DyslexicStoner240.","car":"Space Docker"},"BR8":{"time":25853,"player":"C-200 | Noki | Deputy 1 | CIV","car":"BR8"},"Mini JCW 2020":{"time":29879,"player":"King Rodriguez","car":"Mini JCW 2020"},"Jeep Grand Cherokee TrackhawkPD 2018":{"car":"Jeep Grand Cherokee TrackhawkPD 2018","player":"C-197 | FP-410 | Tristan M. | Deputy I | Probi. FF","time":36165},"School Bus":{"car":"School Bus","player":"227 | Adam | Senior Officer","time":81320},"Nissan Skyline GTR":{"time":29921,"player":"ThatGuyJacobee","car":"Nissan Skyline GTR"},"Ferrari 458":{"time":25352,"player":"Woltage.2","car":"Ferrari 458"},"Dodge Challenger srt 2020 ":{"time":22940,"player":"herediaaldo4","car":"Dodge Challenger srt 2020 "},"Itali GTO":{"time":20103,"player":"ThunderBird","car":"Itali GTO"},"Mercedes AMG GTS":{"time":19029,"player":"vJack","car":"Mercedes AMG GTS"},"Bugatti Chiron 2017":{"time":22371,"player":"King Rodriguez","car":"Bugatti Chiron 2017"},"Dodge Charger 2014":{"time":202399,"player":"C-197 | FP-410 | Tristan M. | Deputy I | Probi. FF","car":"Dodge Charger 2014"},"NULL":{"car":"NULL","player":"C-197 | FP-410 | Tristan M. | Deputy I | Probi. FF","time":4625},"Kawasaki Ninja ZX10R":{"car":"Kawasaki Ninja ZX10R","player":"C-200 | Noki | Deputy 1 | CIV","time":3621},"Projen-C Sports":{"car":"Projen-C Sports","player":"C-200 | Noki | Deputy 1 | CIV","time":93333},"Nero":{"time":34210,"player":"ThunderBird","car":"Nero"},"Chevy Camaro20":{"time":32202,"player":"Max Rodriguez","car":"Chevy Camaro20"},"Corvette C7":{"time":31909,"player":"shrekislove","car":"Corvette C7"},"Neon":{"time":28815,"player":"ThunderBird","car":"Neon"},"Kawasaki Ninja H2":{"time":4998,"player":"C-200 | Noki | Deputy 1 | CIV","car":"Kawasaki Ninja H2"},"Police Rancher":{"car":"Police Rancher","player":"~r~ ¦ 1A-80","time":8092},"2016 Ford Explorer":{"time":26526,"player":"King Rodriguez","car":"2016 Ford Explorer"},"Jeep TrackHawk 2018":{"time":22887,"player":"King Rodriguez","car":"Jeep TrackHawk 2018"},"Verlierer":{"time":31698,"player":"kiyin","car":"Verlierer"},"Dodge Ram 2dr 1500 srt 2010":{"time":21999,"player":"Max Rodriguez ","car":"Dodge Ram 2dr 1500 srt 2010"}},"Observatory Loop":{"NULL":{"time":34126,"player":"ThatGuyJacobee","car":"NULL"}},"North Rallycross ":{"Neon":{"time":351612,"player":"ThunderBird","car":"Neon"}},"Highway Sprint":{"NULL":{"time":93300,"player":"vJack","car":"NULL"}},"Sandy Airfield":{"RE-7B":{"time":28456,"player":"*ZbyniU*","car":"RE-7B"},"Maverick":{"time":29165,"player":"vJack","car":"Maverick"},"NULL":{"time":5607,"player":"ThatGuyJacobee","car":"NULL"},"FH-1 Hunter":{"time":36289,"player":"*ZbyniU*","car":"FH-1 Hunter"},"Neon":{"time":30312,"player":"ThunderBird","car":"Neon"},"BMX":{"time":21014,"player":"vJack","car":"BMX"},"Vigilante":{"time":6172,"player":"*ZbyniU*","car":"Vigilante"},"Oppressor":{"time":21360,"player":"michael82","car":"Oppressor"},"Jester":{"time":47982,"player":"michael82","car":"Jester"}},"Race | Airport Drag":{"2010 Chevy Tahoe":{"time":12821,"player":"King Rodriguez","car":"2010 Chevy Tahoe"},"BMW M5 Plus":{"time":8652,"player":"King Rodriguez","car":"BMW M5 Plus"},"Formula 1":{"time":7629,"player":"King Rodriguez","car":"Formula 1"},"Nissan Skyline GTR":{"time":9693,"player":"ThatGuyJacobee","car":"Nissan Skyline GTR"},"NULL":{"time":12630,"player":"B. LAO","car":"NULL"},"Police Corvette 2019":{"time":14484,"player":"Woltage.2","car":"Police Corvette 2019"}},"Cannonball Run":{"NULL":{"time":81298,"player":"ThatGuyJacobee","car":"NULL"}},"Hollywood Hills":{"NULL":{"time":120053,"player":"Kryplos125","car":"NULL"}},"Airport Circuit":{"Neon":{"time":92652,"player":"ThunderBird","car":"Neon"},"NULL":{"time":22916,"player":"ThatGuyJacobee","car":"NULL"},"P-996 LAZER":{"time":59216,"player":"ThatGuyJacobee","car":"P-996 LAZER"}},"Race | Observatory Loop":{"Mercedes AMG GTS":{"time":56747,"player":"vJack","car":"Mercedes AMG GTS"},"2013 Dodge Charger":{"time":64004,"player":"vJack","car":"2013 Dodge Charger"},"Gauntlet Classic Custom":{"time":76765,"player":"[C-291][GCF-34][MS-13] K. Lee","car":"Gauntlet Classic Custom"},"BMW M5 Plus":{"time":70752,"player":"[EGRP-02]King Rodriguez","car":"BMW M5 Plus"},"Formula 1":{"time":54744,"player":"ThatGuyJacobee","car":"Formula 1"},"NULL":{"time":55388,"player":"[YJ-18] Sinapsey","car":"NULL"},"Porsche 911 GT3RS":{"time":106410,"player":"[YJ-18] Sinapsey","car":"Porsche 911 GT3RS"},"Mazda Miata":{"time":79814,"player":"[C-291][GCF-34][MS-13] K. Lee","car":"Mazda Miata"},"BMW M5":{"time":81837,"player":"[C-291][GCF-34][MS-13] K. Lee","car":"BMW M5"},"Nissan Skyline GTR":{"time":67881,"player":"[C-291][GCF-34][MS-13] K. Lee","car":"Nissan Skyline GTR"},"Ford F-150 Lightning 2022":{"time":68440,"player":"ThatGuyJacobee","car":"Ford F-150 Lightning 2022"}},"Race | Airport Drag Race":{"NULL":{"time":9270,"player":"DR-KingRodriguez","car":"NULL"}}}
\ No newline at end of file
diff --git a/resources/ghmattimysql/__resource.lua b/resources/ghmattimysql/__resource.lua
deleted file mode 100644
index a0722efa3..000000000
--- a/resources/ghmattimysql/__resource.lua
+++ /dev/null
@@ -1,6 +0,0 @@
-resource_manifest_version '44febabe-d386-4d18-afbe-5e627f4af937'
-
-server_scripts {
- 'ghmattimysql.js',
- 'ghmattimysql.lua',
-}
diff --git a/resources/ghmattimysql/config.json b/resources/ghmattimysql/config.json
deleted file mode 100644
index 3bb747360..000000000
--- a/resources/ghmattimysql/config.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "user": "root",
- "password": "Elite_Gaming_13",
- "host": "localhost",
- "port": 3306,
- "database": "fivem",
- "connectionLimit": 10,
- "dateStrings": true
-}
diff --git a/resources/ghmattimysql/ghmattimysql.js b/resources/ghmattimysql/ghmattimysql.js
deleted file mode 100644
index 1a3a911ae..000000000
--- a/resources/ghmattimysql/ghmattimysql.js
+++ /dev/null
@@ -1,608 +0,0 @@
-/******/ (function(modules) { // webpackBootstrap
-/******/ // The module cache
-/******/ var installedModules = {};
-/******/
-/******/ // The require function
-/******/ function __webpack_require__(moduleId) {
-/******/
-/******/ // Check if module is in cache
-/******/ if(installedModules[moduleId]) {
-/******/ return installedModules[moduleId].exports;
-/******/ }
-/******/ // Create a new module (and put it into the cache)
-/******/ var module = installedModules[moduleId] = {
-/******/ i: moduleId,
-/******/ l: false,
-/******/ exports: {}
-/******/ };
-/******/
-/******/ // Execute the module function
-/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
-/******/
-/******/ // Flag the module as loaded
-/******/ module.l = true;
-/******/
-/******/ // Return the exports of the module
-/******/ return module.exports;
-/******/ }
-/******/
-/******/
-/******/ // expose the modules object (__webpack_modules__)
-/******/ __webpack_require__.m = modules;
-/******/
-/******/ // expose the module cache
-/******/ __webpack_require__.c = installedModules;
-/******/
-/******/ // define getter function for harmony exports
-/******/ __webpack_require__.d = function(exports, name, getter) {
-/******/ if(!__webpack_require__.o(exports, name)) {
-/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
-/******/ }
-/******/ };
-/******/
-/******/ // define __esModule on exports
-/******/ __webpack_require__.r = function(exports) {
-/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
-/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
-/******/ }
-/******/ Object.defineProperty(exports, '__esModule', { value: true });
-/******/ };
-/******/
-/******/ // create a fake namespace object
-/******/ // mode & 1: value is a module id, require it
-/******/ // mode & 2: merge all properties of value into the ns
-/******/ // mode & 4: return value when already ns object
-/******/ // mode & 8|1: behave like require
-/******/ __webpack_require__.t = function(value, mode) {
-/******/ if(mode & 1) value = __webpack_require__(value);
-/******/ if(mode & 8) return value;
-/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
-/******/ var ns = Object.create(null);
-/******/ __webpack_require__.r(ns);
-/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
-/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
-/******/ return ns;
-/******/ };
-/******/
-/******/ // getDefaultExport function for compatibility with non-harmony modules
-/******/ __webpack_require__.n = function(module) {
-/******/ var getter = module && module.__esModule ?
-/******/ function getDefault() { return module['default']; } :
-/******/ function getModuleExports() { return module; };
-/******/ __webpack_require__.d(getter, 'a', getter);
-/******/ return getter;
-/******/ };
-/******/
-/******/ // Object.prototype.hasOwnProperty.call
-/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
-/******/
-/******/ // __webpack_public_path__
-/******/ __webpack_require__.p = "";
-/******/
-/******/
-/******/ // Load entry module and return exports
-/******/ return __webpack_require__(__webpack_require__.s = 30);
-/******/ })
-/************************************************************************/
-/******/ ([
-/* 0 */
-/***/ (function(module, exports) {
-
-module.exports = require("util");
-
-/***/ }),
-/* 1 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var buffer=__webpack_require__(39);var Buffer=buffer.Buffer;function copyProps(src,dst){for(var key in src){dst[key]=src[key];}}if(Buffer.from&&Buffer.alloc&&Buffer.allocUnsafe&&Buffer.allocUnsafeSlow){module.exports=buffer;}else{copyProps(buffer,exports);exports.Buffer=SafeBuffer;}function SafeBuffer(arg,encodingOrOffset,length){return Buffer(arg,encodingOrOffset,length);}copyProps(Buffer,SafeBuffer);SafeBuffer.from=function(arg,encodingOrOffset,length){if(typeof arg==='number'){throw new TypeError('Argument must not be a number');}return Buffer(arg,encodingOrOffset,length);};SafeBuffer.alloc=function(size,fill,encoding){if(typeof size!=='number'){throw new TypeError('Argument must be a number');}var buf=Buffer(size);if(fill!==undefined){if(typeof encoding==='string'){buf.fill(fill,encoding);}else{buf.fill(fill);}}else{buf.fill(0);}return buf;};SafeBuffer.allocUnsafe=function(size){if(typeof size!=='number'){throw new TypeError('Argument must be a number');}return Buffer(size);};SafeBuffer.allocUnsafeSlow=function(size){if(typeof size!=='number'){throw new TypeError('Argument must be a number');}return buffer.SlowBuffer(size);};
-
-/***/ }),
-/* 2 */
-/***/ (function(module, exports, __webpack_require__) {
-
-exports.AuthSwitchRequestPacket=__webpack_require__(43);exports.AuthSwitchResponsePacket=__webpack_require__(44);exports.ClientAuthenticationPacket=__webpack_require__(45);exports.ComChangeUserPacket=__webpack_require__(46);exports.ComPingPacket=__webpack_require__(47);exports.ComQueryPacket=__webpack_require__(48);exports.ComQuitPacket=__webpack_require__(49);exports.ComStatisticsPacket=__webpack_require__(50);exports.EmptyPacket=__webpack_require__(51);exports.EofPacket=__webpack_require__(52);exports.ErrorPacket=__webpack_require__(53);exports.Field=__webpack_require__(17);exports.FieldPacket=__webpack_require__(54);exports.HandshakeInitializationPacket=__webpack_require__(55);exports.LocalDataFilePacket=__webpack_require__(56);exports.OkPacket=__webpack_require__(57);exports.OldPasswordPacket=__webpack_require__(58);exports.ResultSetHeaderPacket=__webpack_require__(59);exports.RowDataPacket=__webpack_require__(60);exports.SSLRequestPacket=__webpack_require__(61);exports.StatisticsPacket=__webpack_require__(62);exports.UseOldPasswordPacket=__webpack_require__(63);
-
-/***/ }),
-/* 3 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var Util=__webpack_require__(0);var EventEmitter=__webpack_require__(4).EventEmitter;var Packets=__webpack_require__(2);var ErrorConstants=__webpack_require__(64);var listenerCount=EventEmitter.listenerCount||function(emitter,type){return emitter.listeners(type).length;};var LONG_STACK_DELIMITER='\n --------------------\n';module.exports=Sequence;Util.inherits(Sequence,EventEmitter);function Sequence(options,callback){if(typeof options==='function'){callback=options;options={};}EventEmitter.call(this);options=options||{};this._callback=callback;this._callSite=null;this._ended=false;this._timeout=options.timeout;this._idleNext=null;this._idlePrev=null;this._idleStart=null;this._idleTimeout=-1;this._repeat=null;}Sequence.determinePacket=function(byte){switch(byte){case 0x00:return Packets.OkPacket;case 0xfe:return Packets.EofPacket;case 0xff:return Packets.ErrorPacket;default:return undefined;}};Sequence.prototype.hasErrorHandler=function(){return Boolean(this._callback)||listenerCount(this,'error')>1;};Sequence.prototype._packetToError=function(packet){var code=ErrorConstants[packet.errno]||'UNKNOWN_CODE_PLEASE_REPORT';var err=new Error(code+': '+packet.message);err.code=code;err.errno=packet.errno;err.sqlMessage=packet.message;err.sqlState=packet.sqlState;return err;};Sequence.prototype.end=function(err){if(this._ended){return;}this._ended=true;if(err){this._addLongStackTrace(err);}this._callSite=null;try{if(err){this.emit('error',err);}}finally{try{if(this._callback){this._callback.apply(this,arguments);}}finally{this.emit('end');}}};Sequence.prototype['OkPacket']=function(packet){this.end(null,packet);};Sequence.prototype['ErrorPacket']=function(packet){this.end(this._packetToError(packet));};Sequence.prototype.start=function(){};Sequence.prototype._addLongStackTrace=function _addLongStackTrace(err){var callSiteStack=this._callSite&&this._callSite.stack;if(!callSiteStack||typeof callSiteStack!=='string'){return;}if(err.stack.indexOf(LONG_STACK_DELIMITER)!==-1){return;}var index=callSiteStack.indexOf('\n');if(index!==-1){err.stack+=LONG_STACK_DELIMITER+callSiteStack.substr(index+1);}};Sequence.prototype._onTimeout=function _onTimeout(){this.emit('timeout');};
-
-/***/ }),
-/* 4 */
-/***/ (function(module, exports) {
-
-module.exports = require("events");
-
-/***/ }),
-/* 5 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-var processNextTick=__webpack_require__(10);var objectKeys=Object.keys||function(obj){var keys=[];for(var key in obj){keys.push(key);}return keys;};module.exports=Duplex;var util=__webpack_require__(6);util.inherits=__webpack_require__(7);var Readable=__webpack_require__(20);var Writable=__webpack_require__(23);util.inherits(Duplex,Readable);var keys=objectKeys(Writable.prototype);for(var v=0;v>16);return[w2&0xFFFF,w1&0xFFFF];};Auth.mul32=function(a,b){var w1=a[1]*b[1],w2=(a[1]*b[1]>>16&0xFFFF)+(a[0]*b[1]&0xFFFF)+(a[1]*b[0]&0xFFFF);return[w2&0xFFFF,w1&0xFFFF];};Auth.and32=function(a,b){return[a[0]&b[0],a[1]&b[1]];};Auth.shl32=function(a,b){var w1=a[1]<>16;return[w2&0xFFFF,w1&0xFFFF];};Auth.int31Write=function(buffer,number,offset){buffer[offset]=number[0]>>8&0x7F;buffer[offset+1]=number[0]&0xFF;buffer[offset+2]=number[1]>>8&0xFF;buffer[offset+3]=number[1]&0xFF;};Auth.int32Read=function(buffer,offset){return(buffer[offset]<<24)+(buffer[offset+1]<<16)+(buffer[offset+2]<<8)+buffer[offset+3];};
-
-/***/ }),
-/* 19 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var Sequence=__webpack_require__(3);var Util=__webpack_require__(0);var Packets=__webpack_require__(2);var ResultSet=__webpack_require__(67);var ServerStatus=__webpack_require__(68);var fs=__webpack_require__(69);var Readable=__webpack_require__(70);module.exports=Query;Util.inherits(Query,Sequence);function Query(options,callback){Sequence.call(this,options,callback);this.sql=options.sql;this.values=options.values;this.typeCast=options.typeCast===undefined?true:options.typeCast;this.nestTables=options.nestTables||false;this._resultSet=null;this._results=[];this._fields=[];this._index=0;this._loadError=null;}Query.prototype.start=function(){this.emit('packet',new Packets.ComQueryPacket(this.sql));};Query.prototype.determinePacket=function determinePacket(byte,parser){var resultSet=this._resultSet;if(!resultSet){switch(byte){case 0x00:return Packets.OkPacket;case 0xff:return Packets.ErrorPacket;default:return Packets.ResultSetHeaderPacket;}}if(resultSet.eofPackets.length===0){return resultSet.fieldPackets.length0?this._results:undefined;var fields=this._fields.length>0?this._fields:undefined;err.index=this._index;err.sql=this.sql;this.end(err,results,fields);};Query.prototype['ResultSetHeaderPacket']=function(packet){if(packet.fieldCount===null){this._sendLocalDataFile(packet.extra);}else{this._resultSet=new ResultSet(packet);}};Query.prototype['FieldPacket']=function(packet){this._resultSet.fieldPackets.push(packet);};Query.prototype['EofPacket']=function(packet){this._resultSet.eofPackets.push(packet);if(this._resultSet.eofPackets.length===1&&!this._callback){this.emit('fields',this._resultSet.fieldPackets,this._index);}if(this._resultSet.eofPackets.length!==2){return;}if(this._callback){this._results.push(this._resultSet.rows);this._fields.push(this._resultSet.fieldPackets);}this._index++;this._resultSet=null;this._handleFinalResultPacket(packet);};Query.prototype._handleFinalResultPacket=function(packet){if(packet.serverStatus&ServerStatus.SERVER_MORE_RESULTS_EXISTS){return;}var results=this._results.length>1?this._results:this._results[0];var fields=this._fields.length>1?this._fields:this._fields[0];this.end(this._loadError,results,fields);};Query.prototype['RowDataPacket']=function(packet,parser,connection){packet.parse(parser,this._resultSet.fieldPackets,this.typeCast,this.nestTables,connection);if(this._callback){this._resultSet.rows.push(packet);}else{this.emit('result',packet,this._index);}};Query.prototype._sendLocalDataFile=function(path){var self=this;var localStream=fs.createReadStream(path,{flag:'r',encoding:null,autoClose:true});this.on('pause',function(){localStream.pause();});this.on('resume',function(){localStream.resume();});localStream.on('data',function(data){self.emit('packet',new Packets.LocalDataFilePacket(data));});localStream.on('error',function(err){self._loadError=err;localStream.emit('end');});localStream.on('end',function(){self.emit('packet',new Packets.EmptyPacket());});};Query.prototype.stream=function(options){var self=this,stream;options=options||{};options.objectMode=true;stream=new Readable(options);stream._read=function(){self._connection&&self._connection.resume();};stream.once('end',function(){process.nextTick(function(){stream.emit('close');});});this.on('result',function(row,i){if(!stream.push(row))self._connection.pause();stream.emit('result',row,i);});this.on('error',function(err){stream.emit('error',err);});this.on('end',function(){stream.push(null);});this.on('fields',function(fields,i){stream.emit('fields',fields,i);});return stream;};
-
-/***/ }),
-/* 20 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-var processNextTick=__webpack_require__(10);module.exports=Readable;var isArray=__webpack_require__(71);var Duplex;Readable.ReadableState=ReadableState;var EE=__webpack_require__(4).EventEmitter;var EElistenerCount=function(emitter,type){return emitter.listeners(type).length;};var Stream=__webpack_require__(21);var Buffer=__webpack_require__(1).Buffer;var OurUint8Array=global.Uint8Array||function(){};function _uint8ArrayToBuffer(chunk){return Buffer.from(chunk);}function _isUint8Array(obj){return Buffer.isBuffer(obj)||obj instanceof OurUint8Array;}var util=__webpack_require__(6);util.inherits=__webpack_require__(7);var debugUtil=__webpack_require__(0);var debug=void 0;if(debugUtil&&debugUtil.debuglog){debug=debugUtil.debuglog('stream');}else{debug=function(){};}var BufferList=__webpack_require__(73);var destroyImpl=__webpack_require__(22);var StringDecoder;util.inherits(Readable,Stream);var kProxyEvents=['error','close','destroy','pause','resume'];function prependListener(emitter,event,fn){if(typeof emitter.prependListener==='function'){return emitter.prependListener(event,fn);}else{if(!emitter._events||!emitter._events[event])emitter.on(event,fn);else if(isArray(emitter._events[event]))emitter._events[event].unshift(fn);else emitter._events[event]=[fn,emitter._events[event]];}}function ReadableState(options,stream){Duplex=Duplex||__webpack_require__(5);options=options||{};this.objectMode=!!options.objectMode;if(stream instanceof Duplex)this.objectMode=this.objectMode||!!options.readableObjectMode;var hwm=options.highWaterMark;var defaultHwm=this.objectMode?16:16*1024;this.highWaterMark=hwm||hwm===0?hwm:defaultHwm;this.highWaterMark=Math.floor(this.highWaterMark);this.buffer=new BufferList();this.length=0;this.pipes=null;this.pipesCount=0;this.flowing=null;this.ended=false;this.endEmitted=false;this.reading=false;this.sync=true;this.needReadable=false;this.emittedReadable=false;this.readableListening=false;this.resumeScheduled=false;this.destroyed=false;this.defaultEncoding=options.defaultEncoding||'utf8';this.awaitDrain=0;this.readingMore=false;this.decoder=null;this.encoding=null;if(options.encoding){if(!StringDecoder)StringDecoder=__webpack_require__(24).StringDecoder;this.decoder=new StringDecoder(options.encoding);this.encoding=options.encoding;}}function Readable(options){Duplex=Duplex||__webpack_require__(5);if(!(this instanceof Readable))return new Readable(options);this._readableState=new ReadableState(options,this);this.readable=true;if(options){if(typeof options.read==='function')this._read=options.read;if(typeof options.destroy==='function')this._destroy=options.destroy;}Stream.call(this);}Object.defineProperty(Readable.prototype,'destroyed',{get:function(){if(this._readableState===undefined){return false;}return this._readableState.destroyed;},set:function(value){if(!this._readableState){return;}this._readableState.destroyed=value;}});Readable.prototype.destroy=destroyImpl.destroy;Readable.prototype._undestroy=destroyImpl.undestroy;Readable.prototype._destroy=function(err,cb){this.push(null);cb(err);};Readable.prototype.push=function(chunk,encoding){var state=this._readableState;var skipChunkCheck;if(!state.objectMode){if(typeof chunk==='string'){encoding=encoding||state.defaultEncoding;if(encoding!==state.encoding){chunk=Buffer.from(chunk,encoding);encoding='';}skipChunkCheck=true;}}else{skipChunkCheck=true;}return readableAddChunk(this,chunk,encoding,false,skipChunkCheck);};Readable.prototype.unshift=function(chunk){return readableAddChunk(this,chunk,null,true,false);};function readableAddChunk(stream,chunk,encoding,addToFront,skipChunkCheck){var state=stream._readableState;if(chunk===null){state.reading=false;onEofChunk(stream,state);}else{var er;if(!skipChunkCheck)er=chunkInvalid(state,chunk);if(er){stream.emit('error',er);}else if(state.objectMode||chunk&&chunk.length>0){if(typeof chunk!=='string'&&!state.objectMode&&Object.getPrototypeOf(chunk)!==Buffer.prototype){chunk=_uint8ArrayToBuffer(chunk);}if(addToFront){if(state.endEmitted)stream.emit('error',new Error('stream.unshift() after end event'));else addChunk(stream,state,chunk,true);}else if(state.ended){stream.emit('error',new Error('stream.push() after EOF'));}else{state.reading=false;if(state.decoder&&!encoding){chunk=state.decoder.write(chunk);if(state.objectMode||chunk.length!==0)addChunk(stream,state,chunk,false);else maybeReadMore(stream,state);}else{addChunk(stream,state,chunk,false);}}}else if(!addToFront){state.reading=false;}}return needMoreData(state);}function addChunk(stream,state,chunk,addToFront){if(state.flowing&&state.length===0&&!state.sync){stream.emit('data',chunk);stream.read(0);}else{state.length+=state.objectMode?1:chunk.length;if(addToFront)state.buffer.unshift(chunk);else state.buffer.push(chunk);if(state.needReadable)emitReadable(stream);}maybeReadMore(stream,state);}function chunkInvalid(state,chunk){var er;if(!_isUint8Array(chunk)&&typeof chunk!=='string'&&chunk!==undefined&&!state.objectMode){er=new TypeError('Invalid non-string/buffer chunk');}return er;}function needMoreData(state){return!state.ended&&(state.needReadable||state.length=MAX_HWM){n=MAX_HWM;}else{n--;n|=n>>>1;n|=n>>>2;n|=n>>>4;n|=n>>>8;n|=n>>>16;n++;}return n;}function howMuchToRead(n,state){if(n<=0||state.length===0&&state.ended)return 0;if(state.objectMode)return 1;if(n!==n){if(state.flowing&&state.length)return state.buffer.head.data.length;else return state.length;}if(n>state.highWaterMark)state.highWaterMark=computeNewHighWaterMark(n);if(n<=state.length)return n;if(!state.ended){state.needReadable=true;return 0;}return state.length;}Readable.prototype.read=function(n){debug('read',n);n=parseInt(n,10);var state=this._readableState;var nOrig=n;if(n!==0)state.emittedReadable=false;if(n===0&&state.needReadable&&(state.length>=state.highWaterMark||state.ended)){debug('read: emitReadable',state.length,state.ended);if(state.length===0&&state.ended)endReadable(this);else emitReadable(this);return null;}n=howMuchToRead(n,state);if(n===0&&state.ended){if(state.length===0)endReadable(this);return null;}var doRead=state.needReadable;debug('need readable',doRead);if(state.length===0||state.length-n0)ret=fromList(n,state);else ret=null;if(ret===null){state.needReadable=true;n=0;}else{state.length-=n;}if(state.length===0){if(!state.ended)state.needReadable=true;if(nOrig!==n&&state.ended)endReadable(this);}if(ret!==null)this.emit('data',ret);return ret;};function onEofChunk(stream,state){if(state.ended)return;if(state.decoder){var chunk=state.decoder.end();if(chunk&&chunk.length){state.buffer.push(chunk);state.length+=state.objectMode?1:chunk.length;}}state.ended=true;emitReadable(stream);}function emitReadable(stream){var state=stream._readableState;state.needReadable=false;if(!state.emittedReadable){debug('emitReadable',state.flowing);state.emittedReadable=true;if(state.sync)processNextTick(emitReadable_,stream);else emitReadable_(stream);}}function emitReadable_(stream){debug('emit readable');stream.emit('readable');flow(stream);}function maybeReadMore(stream,state){if(!state.readingMore){state.readingMore=true;processNextTick(maybeReadMore_,stream,state);}}function maybeReadMore_(stream,state){var len=state.length;while(!state.reading&&!state.flowing&&!state.ended&&state.length1&&indexOf(state.pipes,dest)!==-1)&&!cleanedUp){debug('false write response, pause',src._readableState.awaitDrain);src._readableState.awaitDrain++;increasedAwaitDrain=true;}src.pause();}}function onerror(er){debug('onerror',er);unpipe();dest.removeListener('error',onerror);if(EElistenerCount(dest,'error')===0)dest.emit('error',er);}prependListener(dest,'error',onerror);function onclose(){dest.removeListener('finish',onfinish);unpipe();}dest.once('close',onclose);function onfinish(){debug('onfinish');dest.removeListener('close',onclose);unpipe();}dest.once('finish',onfinish);function unpipe(){debug('unpipe');src.unpipe(dest);}dest.emit('pipe',src);if(!state.flowing){debug('pipe resume');src.resume();}return dest;};function pipeOnDrain(src){return function(){var state=src._readableState;debug('pipeOnDrain',state.awaitDrain);if(state.awaitDrain)state.awaitDrain--;if(state.awaitDrain===0&&EElistenerCount(src,'data')){state.flowing=true;flow(src);}};}Readable.prototype.unpipe=function(dest){var state=this._readableState;var unpipeInfo={hasUnpiped:false};if(state.pipesCount===0)return this;if(state.pipesCount===1){if(dest&&dest!==state.pipes)return this;if(!dest)dest=state.pipes;state.pipes=null;state.pipesCount=0;state.flowing=false;if(dest)dest.emit('unpipe',this,unpipeInfo);return this;}if(!dest){var dests=state.pipes;var len=state.pipesCount;state.pipes=null;state.pipesCount=0;state.flowing=false;for(var i=0;i=state.length){if(state.decoder)ret=state.buffer.join('');else if(state.buffer.length===1)ret=state.buffer.head.data;else ret=state.buffer.concat(state.length);state.buffer.clear();}else{ret=fromListPartial(n,state.buffer,state.decoder);}return ret;}function fromListPartial(n,list,hasStrings){var ret;if(nstr.length?str.length:n;if(nb===str.length)ret+=str;else ret+=str.slice(0,n);n-=nb;if(n===0){if(nb===str.length){++c;if(p.next)list.head=p.next;else list.head=list.tail=null;}else{list.head=p;p.data=str.slice(nb);}break;}++c;}list.length-=c;return ret;}function copyFromBuffer(n,list){var ret=Buffer.allocUnsafe(n);var p=list.head;var c=1;p.data.copy(ret);n-=p.data.length;while(p=p.next){var buf=p.data;var nb=n>buf.length?buf.length:n;buf.copy(ret,ret.length-n,0,nb);n-=nb;if(n===0){if(nb===buf.length){++c;if(p.next)list.head=p.next;else list.head=list.tail=null;}else{list.head=p;p.data=buf.slice(nb);}break;}++c;}list.length-=c;return ret;}function endReadable(stream){var state=stream._readableState;if(state.length>0)throw new Error('"endReadable()" called on non-empty stream');if(!state.endEmitted){state.ended=true;processNextTick(endReadableNT,state,stream);}}function endReadableNT(state,stream){if(!state.endEmitted&&state.length===0){state.endEmitted=true;stream.readable=false;stream.emit('end');}}function forEach(xs,f){for(var i=0,l=xs.length;i-1?setImmediate:processNextTick;var Duplex;Writable.WritableState=WritableState;var util=__webpack_require__(6);util.inherits=__webpack_require__(7);var internalUtil={deprecate:__webpack_require__(74)};var Stream=__webpack_require__(21);var Buffer=__webpack_require__(1).Buffer;var OurUint8Array=global.Uint8Array||function(){};function _uint8ArrayToBuffer(chunk){return Buffer.from(chunk);}function _isUint8Array(obj){return Buffer.isBuffer(obj)||obj instanceof OurUint8Array;}var destroyImpl=__webpack_require__(22);util.inherits(Writable,Stream);function nop(){}function WritableState(options,stream){Duplex=Duplex||__webpack_require__(5);options=options||{};this.objectMode=!!options.objectMode;if(stream instanceof Duplex)this.objectMode=this.objectMode||!!options.writableObjectMode;var hwm=options.highWaterMark;var defaultHwm=this.objectMode?16:16*1024;this.highWaterMark=hwm||hwm===0?hwm:defaultHwm;this.highWaterMark=Math.floor(this.highWaterMark);this.finalCalled=false;this.needDrain=false;this.ending=false;this.ended=false;this.finished=false;this.destroyed=false;var noDecode=options.decodeStrings===false;this.decodeStrings=!noDecode;this.defaultEncoding=options.defaultEncoding||'utf8';this.length=0;this.writing=false;this.corked=0;this.sync=true;this.bufferProcessing=false;this.onwrite=function(er){onwrite(stream,er);};this.writecb=null;this.writelen=0;this.bufferedRequest=null;this.lastBufferedRequest=null;this.pendingcb=0;this.prefinished=false;this.errorEmitted=false;this.bufferedRequestCount=0;this.corkedRequestsFree=new CorkedRequest(this);}WritableState.prototype.getBuffer=function getBuffer(){var current=this.bufferedRequest;var out=[];while(current){out.push(current);current=current.next;}return out;};(function(){try{Object.defineProperty(WritableState.prototype,'buffer',{get:internalUtil.deprecate(function(){return this.getBuffer();},'_writableState.buffer is deprecated. Use _writableState.getBuffer '+'instead.','DEP0003')});}catch(_){}})();var realHasInstance;if(typeof Symbol==='function'&&Symbol.hasInstance&&typeof Function.prototype[Symbol.hasInstance]==='function'){realHasInstance=Function.prototype[Symbol.hasInstance];Object.defineProperty(Writable,Symbol.hasInstance,{value:function(object){if(realHasInstance.call(this,object))return true;return object&&object._writableState instanceof WritableState;}});}else{realHasInstance=function(object){return object instanceof this;};}function Writable(options){Duplex=Duplex||__webpack_require__(5);if(!realHasInstance.call(Writable,this)&&!(this instanceof Duplex)){return new Writable(options);}this._writableState=new WritableState(options,this);this.writable=true;if(options){if(typeof options.write==='function')this._write=options.write;if(typeof options.writev==='function')this._writev=options.writev;if(typeof options.destroy==='function')this._destroy=options.destroy;if(typeof options.final==='function')this._final=options.final;}Stream.call(this);}Writable.prototype.pipe=function(){this.emit('error',new Error('Cannot pipe, not readable'));};function writeAfterEnd(stream,cb){var er=new Error('write after end');stream.emit('error',er);processNextTick(cb,er);}function validChunk(stream,state,chunk,cb){var valid=true;var er=false;if(chunk===null){er=new TypeError('May not write null values to stream');}else if(typeof chunk!=='string'&&chunk!==undefined&&!state.objectMode){er=new TypeError('Invalid non-string/buffer chunk');}if(er){stream.emit('error',er);processNextTick(cb,er);valid=false;}return valid;}Writable.prototype.write=function(chunk,encoding,cb){var state=this._writableState;var ret=false;var isBuf=_isUint8Array(chunk)&&!state.objectMode;if(isBuf&&!Buffer.isBuffer(chunk)){chunk=_uint8ArrayToBuffer(chunk);}if(typeof encoding==='function'){cb=encoding;encoding=null;}if(isBuf)encoding='buffer';else if(!encoding)encoding=state.defaultEncoding;if(typeof cb!=='function')cb=nop;if(state.ended)writeAfterEnd(this,cb);else if(isBuf||validChunk(this,state,chunk,cb)){state.pendingcb++;ret=writeOrBuffer(this,state,isBuf,chunk,encoding,cb);}return ret;};Writable.prototype.cork=function(){var state=this._writableState;state.corked++;};Writable.prototype.uncork=function(){var state=this._writableState;if(state.corked){state.corked--;if(!state.writing&&!state.corked&&!state.finished&&!state.bufferProcessing&&state.bufferedRequest)clearBuffer(this,state);}};Writable.prototype.setDefaultEncoding=function setDefaultEncoding(encoding){if(typeof encoding==='string')encoding=encoding.toLowerCase();if(!(['hex','utf8','utf-8','ascii','binary','base64','ucs2','ucs-2','utf16le','utf-16le','raw'].indexOf((encoding+'').toLowerCase())>-1))throw new TypeError('Unknown encoding: '+encoding);this._writableState.defaultEncoding=encoding;return this;};function decodeChunk(state,chunk,encoding){if(!state.objectMode&&state.decodeStrings!==false&&typeof chunk==='string'){chunk=Buffer.from(chunk,encoding);}return chunk;}function writeOrBuffer(stream,state,isBuf,chunk,encoding,cb){if(!isBuf){var newChunk=decodeChunk(state,chunk,encoding);if(chunk!==newChunk){isBuf=true;encoding='buffer';chunk=newChunk;}}var len=state.objectMode?1:chunk.length;state.length+=len;var ret=state.length>5===0x06)return 2;else if(byte>>4===0x0E)return 3;else if(byte>>3===0x1E)return 4;return-1;}function utf8CheckIncomplete(self,buf,i){var j=buf.length-1;if(j=0){if(nb>0)self.lastNeed=nb-1;return nb;}if(--j=0){if(nb>0)self.lastNeed=nb-2;return nb;}if(--j=0){if(nb>0){if(nb===2)nb=0;else self.lastNeed=nb-3;}return nb;}return 0;}function utf8CheckExtraBytes(self,buf,p){if((buf[0]&0xC0)!==0x80){self.lastNeed=0;return'\ufffd'.repeat(p);}if(self.lastNeed>1&&buf.length>1){if((buf[1]&0xC0)!==0x80){self.lastNeed=1;return'\ufffd'.repeat(p+1);}if(self.lastNeed>2&&buf.length>2){if((buf[2]&0xC0)!==0x80){self.lastNeed=2;return'\ufffd'.repeat(p+2);}}}}function utf8FillLast(buf){var p=this.lastTotal-this.lastNeed;var r=utf8CheckExtraBytes(this,buf,p);if(r!==undefined)return r;if(this.lastNeed<=buf.length){buf.copy(this.lastChar,p,0,this.lastNeed);return this.lastChar.toString(this.encoding,0,this.lastTotal);}buf.copy(this.lastChar,p,0,buf.length);this.lastNeed-=buf.length;}function utf8Text(buf,i){var total=utf8CheckIncomplete(this,buf,i);if(!this.lastNeed)return buf.toString('utf8',i);this.lastTotal=total;var end=buf.length-(total-this.lastNeed);buf.copy(this.lastChar,0,end);return buf.toString('utf8',i,end);}function utf8End(buf){var r=buf&&buf.length?this.write(buf):'';if(this.lastNeed)return r+'\ufffd'.repeat(this.lastTotal-this.lastNeed);return r;}function utf16Text(buf,i){if((buf.length-i)%2===0){var r=buf.toString('utf16le',i);if(r){var c=r.charCodeAt(r.length-1);if(c>=0xD800&&c<=0xDBFF){this.lastNeed=2;this.lastTotal=4;this.lastChar[0]=buf[buf.length-2];this.lastChar[1]=buf[buf.length-1];return r.slice(0,-1);}}return r;}this.lastNeed=1;this.lastTotal=2;this.lastChar[0]=buf[buf.length-1];return buf.toString('utf16le',i,buf.length-1);}function utf16End(buf){var r=buf&&buf.length?this.write(buf):'';if(this.lastNeed){var end=this.lastTotal-this.lastNeed;return r+this.lastChar.toString('utf16le',0,end);}return r;}function base64Text(buf,i){var n=(buf.length-i)%3;if(n===0)return buf.toString('base64',i);this.lastNeed=3-n;this.lastTotal=3;if(n===1){this.lastChar[0]=buf[buf.length-1];}else{this.lastChar[0]=buf[buf.length-2];this.lastChar[1]=buf[buf.length-1];}return buf.toString('base64',i,buf.length-n);}function base64End(buf){var r=buf&&buf.length?this.write(buf):'';if(this.lastNeed)return r+this.lastChar.toString('base64',0,3-this.lastNeed);return r;}function simpleWrite(buf){return buf.toString(this.encoding);}function simpleEnd(buf){return buf&&buf.length?this.write(buf):'';}
-
-/***/ }),
-/* 25 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-module.exports=Transform;var Duplex=__webpack_require__(5);var util=__webpack_require__(6);util.inherits=__webpack_require__(7);util.inherits(Transform,Duplex);function TransformState(stream){this.afterTransform=function(er,data){return afterTransform(stream,er,data);};this.needTransform=false;this.transforming=false;this.writecb=null;this.writechunk=null;this.writeencoding=null;}function afterTransform(stream,er,data){var ts=stream._transformState;ts.transforming=false;var cb=ts.writecb;if(!cb){return stream.emit('error',new Error('write callback called multiple times'));}ts.writechunk=null;ts.writecb=null;if(data!==null&&data!==undefined)stream.push(data);cb(er);var rs=stream._readableState;rs.reading=false;if(rs.needReadable||rs.length0){connection=this._freeConnections.shift();this.acquireConnection(connection,cb);return;}if(this.config.connectionLimit===0||this._allConnections.length=this.config.queueLimit){process.nextTick(function(){var err=new Error('Queue limit reached.');err.code='POOL_ENQUEUELIMIT';callback(err);});return;}var cb=process.domain?process.domain.bind(callback):callback;this._connectionQueue.push(cb);this.emit('enqueue');};Pool.prototype._needsChangeUser=function _needsChangeUser(connection){var connConfig=connection.config;var poolConfig=this.config.connectionConfig;return connConfig.user!==poolConfig.user||connConfig.database!==poolConfig.database||connConfig.password!==poolConfig.password||connConfig.charsetNumber!==poolConfig.charsetNumber;};Pool.prototype._purgeConnection=function _purgeConnection(connection,callback){var cb=callback||function(){};if(connection.state==='disconnected'){connection.destroy();}this._removeConnection(connection);if(connection.state!=='disconnected'&&!connection._protocol._quitSequence){connection._realEnd(cb);return;}process.nextTick(cb);};Pool.prototype._removeConnection=function(connection){connection._pool=null;spliceConnection(this._allConnections,connection);spliceConnection(this._freeConnections,connection);this.releaseConnection(connection);};Pool.prototype.escape=function(value){return mysql.escape(value,this.config.connectionConfig.stringifyObjects,this.config.connectionConfig.timezone);};Pool.prototype.escapeId=function escapeId(value){return mysql.escapeId(value,false);};function spliceConnection(array,connection){var index;if((index=array.indexOf(connection))!==-1){array.splice(index,1);}}
-
-/***/ }),
-/* 28 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var ConnectionConfig=__webpack_require__(11);module.exports=PoolConfig;function PoolConfig(options){if(typeof options==='string'){options=ConnectionConfig.parseUrl(options);}this.acquireTimeout=options.acquireTimeout===undefined?10*1000:Number(options.acquireTimeout);this.connectionConfig=new ConnectionConfig(options);this.waitForConnections=options.waitForConnections===undefined?true:Boolean(options.waitForConnections);this.connectionLimit=options.connectionLimit===undefined?10:Number(options.connectionLimit);this.queueLimit=options.queueLimit===undefined?0:Number(options.queueLimit);}PoolConfig.prototype.newConnectionConfig=function newConnectionConfig(){var connectionConfig=new ConnectionConfig(this.connectionConfig);connectionConfig.clientFlags=this.connectionConfig.clientFlags;connectionConfig.maxPacketSize=this.connectionConfig.maxPacketSize;return connectionConfig;};
-
-/***/ }),
-/* 29 */
-/***/ (function(module, exports) {
-
-var PoolSelector=module.exports={};PoolSelector.RR=function PoolSelectorRoundRobin(){var index=0;return function(clusterIds){if(index>=clusterIds.length){index=0;}var clusterId=clusterIds[index++];return clusterId;};};PoolSelector.RANDOM=function PoolSelectorRandom(){return function(clusterIds){return clusterIds[Math.floor(Math.random()*clusterIds.length)];};};PoolSelector.ORDER=function PoolSelectorOrder(){return function(clusterIds){return clusterIds[0];};};
-
-/***/ }),
-/* 30 */
-/***/ (function(module, exports, __webpack_require__) {
-
-const mysql=__webpack_require__(14);const config=JSON.parse(global.LoadResourceFile('ghmattimysql','config.json'));const configString=global.GetConvar('mysql_connection_string','mysql://localhost/fivem');const useBoolean=global.GetConvarInt('mysql_use_boolean',0);const showDebug=global.GetConvarInt('mysql_debug',0);const pool=mysql.createPool(config||configString);function prepareLegacyQuery(query,parameters){let sql=query;let params=parameters;if(params!==null&&typeof params==='object'&&!Array.isArray(params)){params=[];sql=sql.replace(/@(\w+)/g,(txt,key)=>{if(Object.prototype.hasOwnProperty.call(parameters,key)){params.push(parameters[key]);return'?';}return txt;});}return[sql,params];}function transformToBoolean(fields,result){const res=result;if(fields){fields.forEach(field=>{if(field.columnType===1&&field.columnLength===1){result.forEach((_,index)=>{res[index][field.name]=result[index][field.name]!==0;});}});}return res;}function sanitizeInput(query,parameters,callback){let sql=query;let params=parameters;let cb=callback;if(typeof parameters==='function'){cb=parameters;}[sql,params]=prepareLegacyQuery(query,params);if(!Array.isArray(params)){params=[];}return[sql,params,cb];}async function safeInvoke(callback,args){if(typeof callback==='function'){setImmediate(()=>{callback(args);});}}function execute(sql,params,connection){const orm=connection||pool;return new Promise((resolve,reject)=>{orm.query(sql,params,(error,result,fields)=>{if(showDebug)console.log(`[MySQL] ${sql} : ${JSON.stringify(params)}`);if(error)reject(error);resolve(useBoolean?transformToBoolean(fields,result):result);});});}global.exports('scalar',(query,parameters,callback)=>{let sql=query;let params=parameters;let cb=callback;[sql,params,cb]=sanitizeInput(sql,params,cb);execute(sql,params).then(result=>{safeInvoke(cb,Object.values(result[0]||{})[0]);});});global.exports('execute',(query,parameters,callback)=>{let sql=query;let params=parameters;let cb=callback;[sql,params,cb]=sanitizeInput(sql,params,cb);execute(sql,params).then(result=>{safeInvoke(cb,result);});});function onTransactionError(error,connection,callback){connection.rollback(()=>{console.error(error);safeInvoke(callback,false);});}global.exports('transaction',(querys,parameters,callback)=>{let sqls=[];let params=parameters;let cb=callback;if(!querys.every(element=>typeof element==='string')){sqls=querys;if(typeof parameters==='function')cb=parameters;}else{if(typeof parameters==='function'){cb=parameters;params=[];}querys.forEach(element=>{sqls.push({query:element,parameters:params});});}sqls.forEach((element,index)=>{const[stmt,stmtParams]=prepareLegacyQuery(element.query,element.parameters);sqls[index]={query:stmt,parameters:Array.isArray(stmtParams)?stmtParams:[]};});pool.getConnection((connectionError,connection)=>{if(connectionError){console.error(connectionError);safeInvoke(cb,false);return;}connection.beginTransaction(transactionError=>{if(transactionError){onTransactionError(transactionError,connection,callback);return;}const promises=[];sqls.forEach(element=>{promises.push(execute(element.query,element.parameters,connection));});Promise.all(promises).then(()=>{connection.commit(commitError=>{if(commitError){onTransactionError(commitError,connection,callback);}else safeInvoke(cb,true);});}).catch(executeError=>{onTransactionError(executeError,connection,callback);});});});});
-
-/***/ }),
-/* 31 */
-/***/ (function(module, exports) {
-
-module.exports = require("net");
-
-/***/ }),
-/* 32 */
-/***/ (function(module, exports) {
-
-module.exports = require("tls");
-
-/***/ }),
-/* 33 */
-/***/ (function(module, exports) {
-
-module.exports = require("url");
-
-/***/ }),
-/* 34 */
-/***/ (function(module, exports) {
-
-exports['Amazon RDS']={ca:['-----BEGIN CERTIFICATE-----\n'+'MIIDQzCCAqygAwIBAgIJAOd1tlfiGoEoMA0GCSqGSIb3DQEBBQUAMHUxCzAJBgNV\n'+'BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdTZWF0dGxlMRMw\n'+'EQYDVQQKEwpBbWF6b24uY29tMQwwCgYDVQQLEwNSRFMxHDAaBgNVBAMTE2F3cy5h\n'+'bWF6b24uY29tL3Jkcy8wHhcNMTAwNDA1MjI0NDMxWhcNMTUwNDA0MjI0NDMxWjB1\n'+'MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHU2Vh\n'+'dHRsZTETMBEGA1UEChMKQW1hem9uLmNvbTEMMAoGA1UECxMDUkRTMRwwGgYDVQQD\n'+'ExNhd3MuYW1hem9uLmNvbS9yZHMvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n'+'gQDKhXGU7tizxUR5WaFoMTFcxNxa05PEjZaIOEN5ctkWrqYSRov0/nOMoZjqk8bC\n'+'med9vPFoQGD0OTakPs0jVe3wwmR735hyVwmKIPPsGlaBYj1O6llIpZeQVyupNx56\n'+'UzqtiLaDzh1KcmfqP3qP2dInzBfJQKjiRudo1FWnpPt33QIDAQABo4HaMIHXMB0G\n'+'A1UdDgQWBBT/H3x+cqSkR/ePSIinPtc4yWKe3DCBpwYDVR0jBIGfMIGcgBT/H3x+\n'+'cqSkR/ePSIinPtc4yWKe3KF5pHcwdTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh\n'+'c2hpbmd0b24xEDAOBgNVBAcTB1NlYXR0bGUxEzARBgNVBAoTCkFtYXpvbi5jb20x\n'+'DDAKBgNVBAsTA1JEUzEcMBoGA1UEAxMTYXdzLmFtYXpvbi5jb20vcmRzL4IJAOd1\n'+'tlfiGoEoMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAvguZy/BDT66x\n'+'GfgnJlyQwnFSeVLQm9u/FIvz4huGjbq9dqnD6h/Gm56QPFdyMEyDiZWaqY6V08lY\n'+'LTBNb4kcIc9/6pc0/ojKciP5QJRm6OiZ4vgG05nF4fYjhU7WClUx7cxq1fKjNc2J\n'+'UCmmYqgiVkAGWRETVo+byOSDZ4swb10=\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIID9DCCAtygAwIBAgIBQjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUwOTExMzFaFw0y\n'+'MDAzMDUwOTExMzFaMIGKMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEbMBkGA1UEAwwSQW1hem9uIFJE\n'+'UyBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuD8nrZ8V\n'+'u+VA8yVlUipCZIKPTDcOILYpUe8Tct0YeQQr0uyl018StdBsa3CjBgvwpDRq1HgF\n'+'Ji2N3+39+shCNspQeE6aYU+BHXhKhIIStt3r7gl/4NqYiDDMWKHxHq0nsGDFfArf\n'+'AOcjZdJagOMqb3fF46flc8k2E7THTm9Sz4L7RY1WdABMuurpICLFE3oHcGdapOb9\n'+'T53pQR+xpHW9atkcf3pf7gbO0rlKVSIoUenBlZipUlp1VZl/OD/E+TtRhDDNdI2J\n'+'P/DSMM3aEsq6ZQkfbz/Ilml+Lx3tJYXUDmp+ZjzMPLk/+3beT8EhrwtcG3VPpvwp\n'+'BIOqsqVVTvw/CwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw\n'+'AwEB/zAdBgNVHQ4EFgQUTgLurD72FchM7Sz1BcGPnIQISYMwHwYDVR0jBBgwFoAU\n'+'TgLurD72FchM7Sz1BcGPnIQISYMwDQYJKoZIhvcNAQEFBQADggEBAHZcgIio8pAm\n'+'MjHD5cl6wKjXxScXKtXygWH2BoDMYBJF9yfyKO2jEFxYKbHePpnXB1R04zJSWAw5\n'+'2EUuDI1pSBh9BA82/5PkuNlNeSTB3dXDD2PEPdzVWbSKvUB8ZdooV+2vngL0Zm4r\n'+'47QPyd18yPHrRIbtBtHR/6CwKevLZ394zgExqhnekYKIqqEX41xsUV0Gm6x4vpjf\n'+'2u6O/+YE2U+qyyxHE5Wd5oqde0oo9UUpFETJPVb6Q2cEeQib8PBAyi0i6KnF+kIV\n'+'A9dY7IHSubtCK/i8wxMVqfd5GtbA8mmpeJFwnDvm9rBEsHybl08qlax9syEwsUYr\n'+'/40NawZfTUU=\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIIEATCCAumgAwIBAgIBRDANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzMDZaFw0y\n'+'MDAzMDUyMjAzMDZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzElMCMGA1UEAwwcQW1hem9uIFJE\n'+'UyBhcC1ub3J0aGVhc3QtMSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n'+'ggEBAMmM2B4PfTXCZjbZMWiDPyxvk/eeNwIRJAhfzesiGUiLozX6CRy3rwC1ZOPV\n'+'AcQf0LB+O8wY88C/cV+d4Q2nBDmnk+Vx7o2MyMh343r5rR3Na+4izd89tkQVt0WW\n'+'vO21KRH5i8EuBjinboOwAwu6IJ+HyiQiM0VjgjrmEr/YzFPL8MgHD/YUHehqjACn\n'+'C0+B7/gu7W4qJzBL2DOf7ub2qszGtwPE+qQzkCRDwE1A4AJmVE++/FLH2Zx78Egg\n'+'fV1sUxPtYgjGH76VyyO6GNKM6rAUMD/q5mnPASQVIXgKbupr618bnH+SWHFjBqZq\n'+'HvDGPMtiiWII41EmGUypyt5AbysCAwEAAaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIG\n'+'A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFIiKM0Q6n1K4EmLxs3ZXxINbwEwR\n'+'MB8GA1UdIwQYMBaAFE4C7qw+9hXITO0s9QXBj5yECEmDMA0GCSqGSIb3DQEBBQUA\n'+'A4IBAQBezGbE9Rw/k2e25iGjj5n8r+M3dlye8ORfCE/dijHtxqAKasXHgKX8I9Tw\n'+'JkBiGWiuzqn7gO5MJ0nMMro1+gq29qjZnYX1pDHPgsRjUX8R+juRhgJ3JSHijRbf\n'+'4qNJrnwga7pj94MhcLq9u0f6dxH6dXbyMv21T4TZMTmcFduf1KgaiVx1PEyJjC6r\n'+'M+Ru+A0eM+jJ7uCjUoZKcpX8xkj4nmSnz9NMPog3wdOSB9cAW7XIc5mHa656wr7I\n'+'WJxVcYNHTXIjCcng2zMKd1aCcl2KSFfy56sRfT7J5Wp69QSr+jq8KM55gw8uqAwi\n'+'VPrXn2899T1rcTtFYFP16WXjGuc0\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIIEATCCAumgAwIBAgIBTDANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTExMDYwMDA1NDZaFw0y\n'+'MDAzMDUwMDA1NDZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzElMCMGA1UEAwwcQW1hem9uIFJE\n'+'UyBhcC1ub3J0aGVhc3QtMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n'+'ggEBAKSwd+RVUzTRH0FgnbwoTK8TMm/zMT4+2BvALpAUe6YXbkisg2goycWuuWLg\n'+'jOpFBB3GtyvXZnkqi7MkDWUmj1a2kf8l2oLyoaZ+Hm9x/sV+IJzOqPvj1XVUGjP6\n'+'yYYnPJmUYqvZeI7fEkIGdFkP2m4/sgsSGsFvpD9FK1bL1Kx2UDpYX0kHTtr18Zm/\n'+'1oN6irqWALSmXMDydb8hE0FB2A1VFyeKE6PnoDj/Y5cPHwPPdEi6/3gkDkSaOG30\n'+'rWeQfL3pOcKqzbHaWTxMphd0DSL/quZ64Nr+Ly65Q5PRcTrtr55ekOUziuqXwk+o\n'+'9QpACMwcJ7ROqOznZTqTzSFVXFECAwEAAaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIG\n'+'A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFM6Nox/QWbhzWVvzoJ/y0kGpNPK+\n'+'MB8GA1UdIwQYMBaAFE4C7qw+9hXITO0s9QXBj5yECEmDMA0GCSqGSIb3DQEBBQUA\n'+'A4IBAQCTkWBqNvyRf3Y/W21DwFx3oT/AIWrHt0BdGZO34tavummXemTH9LZ/mqv9\n'+'aljt6ZuDtf5DEQjdsAwXMsyo03ffnP7doWm8iaF1+Mui77ot0TmTsP/deyGwukvJ\n'+'tkxX8bZjDh+EaNauWKr+CYnniNxCQLfFtXYJsfOdVBzK3xNL+Z3ucOQRhr2helWc\n'+'CDQgwfhP1+3pRVKqHvWCPC4R3fT7RZHuRmZ38kndv476GxRntejh+ePffif78bFI\n'+'3rIZCPBGobrrUMycafSbyXteoGca/kA+/IqrAPlk0pWQ4aEL0yTWN2h2dnjoD7oX\n'+'byIuL/g9AGRh97+ssn7D6bDRPTbW\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIIEATCCAumgAwIBAgIBRTANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzMTlaFw0y\n'+'MDAzMDUyMjAzMTlaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzElMCMGA1UEAwwcQW1hem9uIFJE\n'+'UyBhcC1zb3V0aGVhc3QtMSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n'+'ggEBANaXElmSEYt/UtxHFsARFhSUahTf1KNJzR0Dmay6hqOXQuRVbKRwPd19u5vx\n'+'DdF1sLT7D69IK3VDnUiQScaCv2Dpu9foZt+rLx+cpx1qiQd1UHrvqq8xPzQOqCdC\n'+'RFStq6yVYZ69yfpfoI67AjclMOjl2Vph3ftVnqP0IgVKZdzeC7fd+umGgR9xY0Qr\n'+'Ubhd/lWdsbNvzK3f1TPWcfIKQnpvSt85PIEDJir6/nuJUKMtmJRwTymJf0i+JZ4x\n'+'7dJa341p2kHKcHMgOPW7nJQklGBA70ytjUV6/qebS3yIugr/28mwReflg3TJzVDl\n'+'EOvi6pqbqNbkMuEwGDCmEQIVqgkCAwEAAaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIG\n'+'A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFAu93/4k5xbWOsgdCdn+/KdiRuit\n'+'MB8GA1UdIwQYMBaAFE4C7qw+9hXITO0s9QXBj5yECEmDMA0GCSqGSIb3DQEBBQUA\n'+'A4IBAQBlcjSyscpPjf5+MgzMuAsCxByqUt+WFspwcMCpwdaBeHOPSQrXNqX2Sk6P\n'+'kth6oCivA64trWo8tFMvPYlUA1FYVD5WpN0kCK+P5pD4KHlaDsXhuhClJzp/OP8t\n'+'pOyUr5109RHLxqoKB5J5m1XA7rgcFjnMxwBSWFe3/4uMk/+4T53YfCVXuc6QV3i7\n'+'I/2LAJwFf//pTtt6fZenYfCsahnr2nvrNRNyAxcfvGZ/4Opn/mJtR6R/AjvQZHiR\n'+'bkRNKF2GW0ueK5W4FkZVZVhhX9xh1Aj2Ollb+lbOqADaVj+AT3PoJPZ3MPQHKCXm\n'+'xwG0LOLlRr/TfD6li1AfOVTAJXv9\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIIEATCCAumgAwIBAgIBRjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzMjRaFw0y\n'+'MDAzMDUyMjAzMjRaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzElMCMGA1UEAwwcQW1hem9uIFJE\n'+'UyBhcC1zb3V0aGVhc3QtMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n'+'ggEBAJqBAJutz69hFOh3BtLHZTbwE8eejGGKayn9hu98YMDPzWzGXWCmW+ZYWELA\n'+'cY3cNWNF8K4FqKXFr2ssorBYim1UtYFX8yhydT2hMD5zgQ2sCGUpuidijuPA6zaq\n'+'Z3tdhVR94f0q8mpwpv2zqR9PcqaGDx2VR1x773FupRPRo7mEW1vC3IptHCQlP/zE\n'+'7jQiLl28bDIH2567xg7e7E9WnZToRnhlYdTaDaJsHTzi5mwILi4cihSok7Shv/ME\n'+'hnukvxeSPUpaVtFaBhfBqq055ePq9I+Ns4KGreTKMhU0O9fkkaBaBmPaFgmeX/XO\n'+'n2AX7gMouo3mtv34iDTZ0h6YCGkCAwEAAaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIG\n'+'A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFIlQnY0KHYWn1jYumSdJYfwj/Nfw\n'+'MB8GA1UdIwQYMBaAFE4C7qw+9hXITO0s9QXBj5yECEmDMA0GCSqGSIb3DQEBBQUA\n'+'A4IBAQA0wVU6/l41cTzHc4azc4CDYY2Wd90DFWiH9C/mw0SgToYfCJ/5Cfi0NT/Y\n'+'PRnk3GchychCJgoPA/k9d0//IhYEAIiIDjyFVgjbTkKV3sh4RbdldKVOUB9kumz/\n'+'ZpShplsGt3z4QQiVnKfrAgqxWDjR0I0pQKkxXa6Sjkicos9LQxVtJ0XA4ieG1E7z\n'+'zJr+6t80wmzxvkInSaWP3xNJK9azVRTrgQZQlvkbpDbExl4mNTG66VD3bAp6t3Wa\n'+'B49//uDdfZmPkqqbX+hsxp160OH0rxJppwO3Bh869PkDnaPEd/Pxw7PawC+li0gi\n'+'NRV8iCEx85aFxcyOhqn0WZOasxee\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIID/zCCAuegAwIBAgIBRzANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzMzFaFw0y\n'+'MDAzMDUyMjAzMzFaMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEjMCEGA1UEAwwaQW1hem9uIFJE\n'+'UyBldS1jZW50cmFsLTEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\n'+'AQDFtP2dhSLuaPOI4ZrrPWsK4OY9ocQBp3yApH1KJYmI9wpQKZG/KCH2E6Oo7JAw\n'+'QORU519r033T+FO2Z7pFPlmz1yrxGXyHpJs8ySx3Yo5S8ncDCdZJCLmtPiq/hahg\n'+'5/0ffexMFUCQaYicFZsrJ/cStdxUV+tSw2JQLD7UxS9J97LQWUPyyG+ZrjYVTVq+\n'+'zudnFmNSe4QoecXMhAFTGJFQXxP7nhSL9Ao5FGgdXy7/JWeWdQIAj8ku6cBDKPa6\n'+'Y6kP+ak+In+Lye8z9qsCD/afUozfWjPR2aA4JoIZVF8dNRShIMo8l0XfgfM2q0+n\n'+'ApZWZ+BjhIO5XuoUgHS3D2YFAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNV\n'+'HRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBRm4GsWIA/M6q+tK8WGHWDGh2gcyTAf\n'+'BgNVHSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQUFAAOC\n'+'AQEAHpMmeVQNqcxgfQdbDIi5UIy+E7zZykmtAygN1XQrvga9nXTis4kOTN6g5/+g\n'+'HCx7jIXeNJzAbvg8XFqBN84Quqgpl/tQkbpco9Jh1HDs558D5NnZQxNqH5qXQ3Mm\n'+'uPgCw0pYcPOa7bhs07i+MdVwPBsX27CFDtsgAIru8HvKxY1oTZrWnyIRo93tt/pk\n'+'WuItVMVHjaQZVfTCow0aDUbte6Vlw82KjUFq+n2NMSCJDiDKsDDHT6BJc4AJHIq3\n'+'/4Z52MSC9KMr0yAaaoWfW/yMEj9LliQauAgwVjArF4q78rxpfKTG9Rfd8U1BZANP\n'+'7FrFMN0ThjfA1IvmOYcgskY5bQ==\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIID/DCCAuSgAwIBAgIBSDANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzMzVaFw0y\n'+'MDAzMDUyMjAzMzVaMIGPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEgMB4GA1UEAwwXQW1hem9uIFJE\n'+'UyBldS13ZXN0LTEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx\n'+'PdbqQ0HKRj79Pmocxvjc+P6i4Ux24kgFIl+ckiir1vzkmesc3a58gjrMlCksEObt\n'+'Yihs5IhzEq1ePT0gbfS9GYFp34Uj/MtPwlrfCBWG4d2TcrsKRHr1/EXUYhWqmdrb\n'+'RhX8XqoRhVkbF/auzFSBhTzcGGvZpQ2KIaxRcQfcXlMVhj/pxxAjh8U4F350Fb0h\n'+'nX1jw4/KvEreBL0Xb2lnlGTkwVxaKGSgXEnOgIyOFdOQc61vdome0+eeZsP4jqeR\n'+'TGYJA9izJsRbe2YJxHuazD+548hsPlM3vFzKKEVURCha466rAaYAHy3rKur3HYQx\n'+'Yt+SoKcEz9PXuSGj96ejAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB\n'+'Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBTebg//h2oeXbZjQ4uuoiuLYzuiPDAfBgNV\n'+'HSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQUFAAOCAQEA\n'+'TikPaGeZasTPw+4RBemlsyPAjtFFQLo7ddaFdORLgdEysVf8aBqndvbA6MT/v4lj\n'+'GtEtUdF59ZcbWOrVm+fBZ2h/jYJ59dYF/xzb09nyRbdMSzB9+mkSsnOMqluq5y8o\n'+'DY/PfP2vGhEg/2ZncRC7nlQU1Dm8F4lFWEiQ2fi7O1cW852Vmbq61RIfcYsH/9Ma\n'+'kpgk10VZ75b8m3UhmpZ/2uRY+JEHImH5WpcTJ7wNiPNJsciZMznGtrgOnPzYco8L\n'+'cDleOASIZifNMQi9PKOJKvi0ITz0B/imr8KBsW0YjZVJ54HMa7W1lwugSM7aMAs+\n'+'E3Sd5lS+SHwWaOCHwhOEVA==\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIID/DCCAuSgAwIBAgIBSTANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzNDBaFw0y\n'+'MDAzMDUyMjAzNDBaMIGPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEgMB4GA1UEAwwXQW1hem9uIFJE\n'+'UyBzYS1lYXN0LTEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCU\n'+'X4OBnQ5xA6TLJAiFEI6l7bUWjoVJBa/VbMdCCSs2i2dOKmqUaXu2ix2zcPILj3lZ\n'+'GMk3d/2zvTK/cKhcFrewHUBamTeVHdEmynhMQamqNmkM4ptYzFcvEUw1TGxHT4pV\n'+'Q6gSN7+/AJewQvyHexHo8D0+LDN0/Wa9mRm4ixCYH2CyYYJNKaZt9+EZfNu+PPS4\n'+'8iB0TWH0DgQkbWMBfCRgolLLitAZklZ4dvdlEBS7evN1/7ttBxUK6SvkeeSx3zBl\n'+'ww3BlXqc3bvTQL0A+RRysaVyFbvtp9domFaDKZCpMmDFAN/ntx215xmQdrSt+K3F\n'+'cXdGQYHx5q410CAclGnbAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB\n'+'Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBT6iVWnm/uakS+tEX2mzIfw+8JL0zAfBgNV\n'+'HSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQUFAAOCAQEA\n'+'FmDD+QuDklXn2EgShwQxV13+txPRuVdOSrutHhoCgMwFWCMtPPtBAKs6KPY7Guvw\n'+'DpJoZSehDiOfsgMirjOWjvfkeWSNvKfjWTVneX7pZD9W5WPnsDBvTbCGezm+v87z\n'+'b+ZM2ZMo98m/wkMcIEAgdSKilR2fuw8rLkAjhYFfs0A7tDgZ9noKwgHvoE4dsrI0\n'+'KZYco6DlP/brASfHTPa2puBLN9McK3v+h0JaSqqm5Ro2Bh56tZkQh8AWy/miuDuK\n'+'3+hNEVdxosxlkM1TPa1DGj0EzzK0yoeerXuH2HX7LlCrrxf6/wdKnjR12PMrLQ4A\n'+'pCqkcWw894z6bV9MAvKe6A==\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIID/DCCAuSgAwIBAgIBQzANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMTU0MDRaFw0y\n'+'MDAzMDUyMTU0MDRaMIGPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEgMB4GA1UEAwwXQW1hem9uIFJE\n'+'UyB1cy1lYXN0LTEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDI\n'+'UIuwh8NusKHk1SqPXcP7OqxY3S/M2ZyQWD3w7Bfihpyyy/fc1w0/suIpX3kbMhAV\n'+'2ESwged2/2zSx4pVnjp/493r4luhSqQYzru78TuPt9bhJIJ51WXunZW2SWkisSaf\n'+'USYUzVN9ezR/bjXTumSUQaLIouJt3OHLX49s+3NAbUyOI8EdvgBQWD68H1epsC0n\n'+'CI5s+pIktyOZ59c4DCDLQcXErQ+tNbDC++oct1ANd/q8p9URonYwGCGOBy7sbCYq\n'+'9eVHh1Iy2M+SNXddVOGw5EuruvHoCIQyOz5Lz4zSuZA9dRbrfztNOpezCNYu6NKM\n'+'n+hzcvdiyxv77uNm8EaxAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB\n'+'Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBQSQG3TmMe6Sa3KufaPBa72v4QFDzAfBgNV\n'+'HSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQUFAAOCAQEA\n'+'L/mOZfB3187xTmjOHMqN2G2oSKHBKiQLM9uv8+97qT+XR+TVsBT6b3yoPpMAGhHA\n'+'Pc7nxAF5gPpuzatx0OTLPcmYucFmfqT/1qA5WlgCnMNtczyNMH97lKFTNV7Njtek\n'+'jWEzAEQSyEWrkNpNlC4j6kMYyPzVXQeXUeZTgJ9FNnVZqmvfjip2N22tawMjrCn5\n'+'7KN/zN65EwY2oO9XsaTwwWmBu3NrDdMbzJnbxoWcFWj4RBwanR1XjQOVNhDwmCOl\n'+'/1Et13b8CPyj69PC8BOVU6cfTSx8WUVy0qvYOKHNY9Bqa5BDnIL3IVmUkeTlM1mt\n'+'enRpyBj+Bk9rh/ICdiRKmA==\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIID/DCCAuSgAwIBAgIBSjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzNDVaFw0y\n'+'MDAzMDUyMjAzNDVaMIGPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEgMB4GA1UEAwwXQW1hem9uIFJE\n'+'UyB1cy13ZXN0LTEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDE\n'+'Dhw+uw/ycaiIhhyu2pXFRimq0DlB8cNtIe8hdqndH8TV/TFrljNgR8QdzOgZtZ9C\n'+'zzQ2GRpInN/qJF6slEd6wO+6TaDBQkPY+07TXNt52POFUhdVkhJXHpE2BS7Xn6J7\n'+'7RFAOeG1IZmc2DDt+sR1BgXzUqHslQGfFYNS0/MBO4P+ya6W7IhruB1qfa4HiYQS\n'+'dbe4MvGWnv0UzwAqdR7OF8+8/5c58YXZIXCO9riYF2ql6KNSL5cyDPcYK5VK0+Q9\n'+'VI6vuJHSMYcF7wLePw8jtBktqAFE/wbdZiIHhZvNyiNWPPNTGUmQbaJ+TzQEHDs5\n'+'8en+/W7JKnPyBOkxxENbAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB\n'+'Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBS0nw/tFR9bCjgqWTPJkyy4oOD8bzAfBgNV\n'+'HSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQUFAAOCAQEA\n'+'CXGAY3feAak6lHdqj6+YWjy6yyUnLK37bRxZDsyDVXrPRQaXRzPTzx79jvDwEb/H\n'+'Q/bdQ7zQRWqJcbivQlwhuPJ4kWPUZgSt3JUUuqkMsDzsvj/bwIjlrEFDOdHGh0mi\n'+'eVIngFEjUXjMh+5aHPEF9BlQnB8LfVtKj18e15UDTXFa+xJPFxUR7wDzCfo4WI1m\n'+'sUMG4q1FkGAZgsoyFPZfF8IVvgCuGdR8z30VWKklFxttlK0eGLlPAyIO0CQxPQlo\n'+'saNJrHf4tLOgZIWk+LpDhNd9Et5EzvJ3aURUsKY4pISPPF5WdvM9OE59bERwUErd\n'+'nuOuQWQeeadMceZnauRzJQ==\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIID/DCCAuSgAwIBAgIBSzANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNTAyMDUyMjAzNTBaFw0y\n'+'MDAzMDUyMjAzNTBaMIGPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEgMB4GA1UEAwwXQW1hem9uIFJE\n'+'UyB1cy13ZXN0LTIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDM\n'+'H58SR48U6jyERC1vYTnub34smf5EQVXyzaTmspWGWGzT31NLNZGSDFaa7yef9kdO\n'+'mzJsgebR5tXq6LdwlIoWkKYQ7ycUaadtVKVYdI40QcI3cHn0qLFlg2iBXmWp/B+i\n'+'Z34VuVlCh31Uj5WmhaBoz8t/GRqh1V/aCsf3Wc6jCezH3QfuCjBpzxdOOHN6Ie2v\n'+'xX09O5qmZTvMoRBAvPkxdaPg/Mi7fxueWTbEVk78kuFbF1jHYw8U1BLILIAhcqlq\n'+'x4u8nl73t3O3l/soNUcIwUDK0/S+Kfqhwn9yQyPlhb4Wy3pfnZLJdkyHldktnQav\n'+'9TB9u7KH5Lk0aAYslMLxAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB\n'+'Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBT8roM4lRnlFHWMPWRz0zkwFZog1jAfBgNV\n'+'HSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQUFAAOCAQEA\n'+'JwrxwgwmPtcdaU7O7WDdYa4hprpOMamI49NDzmE0s10oGrqmLwZygcWU0jT+fJ+Y\n'+'pJe1w0CVfKaeLYNsOBVW3X4ZPmffYfWBheZiaiEflq/P6t7/Eg81gaKYnZ/x1Dfa\n'+'sUYkzPvCkXe9wEz5zdUTOCptDt89rBR9CstL9vE7WYUgiVVmBJffWbHQLtfjv6OF\n'+'NMb0QME981kGRzc2WhgP71YS2hHd1kXtsoYP1yTu4vThSKsoN4bkiHsaC1cRkLoy\n'+'0fFA4wpB3WloMEvCDaUvvH1LZlBXTNlwi9KtcwD4tDxkkBt4tQczKLGpQ/nF/W9n\n'+'8YDWk3IIc1sd0bkZqoau2Q==\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIID/TCCAuWgAwIBAgIBTTANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNjA1MDMyMTI5MjJaFw0y\n'+'MDAzMDUyMTI5MjJaMIGQMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEhMB8GA1UEAwwYQW1hem9uIFJE\n'+'UyBhcC1zb3V0aC0xIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\n'+'06eWGLE0TeqL9kyWOLkS8q0fXO97z+xyBV3DKSB2lg2GkgBz3B98MkmkeB0SZy3G\n'+'Ce4uCpCPbFKiFEdiUclOlhZsrBuCeaimxLM3Ig2wuenElO/7TqgaYHYUbT3d+VQW\n'+'GUbLn5GRZJZe1OAClYdOWm7A1CKpuo+cVV1vxbY2nGUQSJPpVn2sT9gnwvjdE60U\n'+'JGYU/RLCTm8zmZBvlWaNIeKDnreIc4rKn6gUnJ2cQn1ryCVleEeyc3xjYDSrjgdn\n'+'FLYGcp9mphqVT0byeQMOk0c7RHpxrCSA0V5V6/CreFV2LteK50qcDQzDSM18vWP/\n'+'p09FoN8O7QrtOeZJzH/lmwIDAQABo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0T\n'+'AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU2i83QHuEl/d0keXF+69HNJph7cMwHwYD\n'+'VR0jBBgwFoAUTgLurD72FchM7Sz1BcGPnIQISYMwDQYJKoZIhvcNAQELBQADggEB\n'+'ACqnH2VjApoDqoSQOky52QBwsGaj+xWYHW5Gm7EvCqvQuhWMkeBuD6YJmMvNyA9G\n'+'I2lh6/o+sUk/RIsbYbxPRdhNPTOgDR9zsNRw6qxaHztq/CEC+mxDCLa3O1hHBaDV\n'+'BmB3nCZb93BvO0EQSEk7aytKq/f+sjyxqOcs385gintdHGU9uM7gTZHnU9vByJsm\n'+'/TL07Miq67X0NlhIoo3jAk+xHaeKJdxdKATQp0448P5cY20q4b8aMk1twcNaMvCP\n'+'dG4M5doaoUA8OQ/0ukLLae/LBxLeTw04q1/a2SyFaVUX2Twbb1S3xVWwLA8vsyGr\n'+'igXx7B5GgP+IHb6DTjPJAi0=\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIID/zCCAuegAwIBAgIBTzANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNjA5MTUwMDEwMTFaFw0y\n'+'MDAzMDUwMDEwMTFaMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEjMCEGA1UEAwwaQW1hem9uIFJE\n'+'UyBjYS1jZW50cmFsLTEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\n'+'AQCZYI/iQ6DrS3ny3t1EwX1wAD+3LMgh7Fd01EW5LIuaK2kYIIQpsVKhxLCit/V5\n'+'AGc/1qiJS1Qz9ODLTh0Na6bZW6EakRzuHJLe32KJtoFYPC7Z09UqzXrpA/XL+1hM\n'+'P0ZmCWsU7Nn/EmvfBp9zX3dZp6P6ATrvDuYaVFr+SA7aT3FXpBroqBS1fyzUPs+W\n'+'c6zTR6+yc4zkHX0XQxC5RH6xjgpeRkoOajA/sNo7AQF7KlWmKHbdVF44cvvAhRKZ\n'+'XaoVs/C4GjkaAEPTCbopYdhzg+KLx9eB2BQnYLRrIOQZtRfbQI2Nbj7p3VsRuOW1\n'+'tlcks2w1Gb0YC6w6SuIMFkl1AgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNV\n'+'HRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBToYWxE1lawl6Ks6NsvpbHQ3GKEtzAf\n'+'BgNVHSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQsFAAOC\n'+'AQEAG/8tQ0ooi3hoQpa5EJz0/E5VYBsAz3YxA2HoIonn0jJyG16bzB4yZt4vNQMA\n'+'KsNlQ1uwDWYL1nz63axieUUFIxqxl1KmwfhsmLgZ0Hd2mnTPIl2Hw3uj5+wdgGBg\n'+'agnAZ0bajsBYgD2VGQbqjdk2Qn7Fjy3LEWIvGZx4KyZ99OJ2QxB7JOPdauURAtWA\n'+'DKYkP4LLJxtj07DSzG8kuRWb9B47uqUD+eKDIyjfjbnzGtd9HqqzYFau7EX3HVD9\n'+'9Qhnjl7bTZ6YfAEZ3nH2t3Vc0z76XfGh47rd0pNRhMV+xpok75asKf/lNh5mcUrr\n'+'VKwflyMkQpSbDCmcdJ90N2xEXQ==\n'+'-----END CERTIFICATE-----\n','-----BEGIN CERTIFICATE-----\n'+'MIID/DCCAuSgAwIBAgIBUDANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMCVVMx\n'+'EzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxIjAgBgNVBAoM\n'+'GUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4xEzARBgNVBAsMCkFtYXpvbiBSRFMx\n'+'GzAZBgNVBAMMEkFtYXpvbiBSRFMgUm9vdCBDQTAeFw0xNjEwMTAxNzQ0NDJaFw0y\n'+'MDAzMDUxNzQ0NDJaMIGPMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n'+'bjEQMA4GA1UEBwwHU2VhdHRsZTEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNl\n'+'cywgSW5jLjETMBEGA1UECwwKQW1hem9uIFJEUzEgMB4GA1UEAwwXQW1hem9uIFJE\n'+'UyBldS13ZXN0LTIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDO\n'+'cttLJfubB4XMMIGWNfJISkIdCMGJyOzLiMJaiWB5GYoXKhEl7YGotpy0qklwW3BQ\n'+'a0fmVdcCLX+dIuVQ9iFK+ZcK7zwm7HtdDTCHOCKeOh2IcnU4c/VIokFi6Gn8udM6\n'+'N/Zi5M5OGpVwLVALQU7Yctsn3c95el6MdVx6mJiIPVu7tCVZn88Z2koBQ2gq9P4O\n'+'Sb249SHFqOb03lYDsaqy1NDsznEOhaRBw7DPJFpvmw1lA3/Y6qrExRI06H2VYR2i\n'+'7qxwDV50N58fs10n7Ye1IOxTVJsgEA7X6EkRRXqYaM39Z76R894548WHfwXWjUsi\n'+'MEX0RS0/t1GmnUQjvevDAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMB\n'+'Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBQBxmcuRSxERYCtNnSr5xNfySokHjAfBgNV\n'+'HSMEGDAWgBROAu6sPvYVyEztLPUFwY+chAhJgzANBgkqhkiG9w0BAQsFAAOCAQEA\n'+'UyCUQjsF3nUAABjfEZmpksTuUo07aT3KGYt+EMMFdejnBQ0+2lJJFGtT+CDAk1SD\n'+'RSgfEBon5vvKEtlnTf9a3pv8WXOAkhfxnryr9FH6NiB8obISHNQNPHn0ljT2/T+I\n'+'Y6ytfRvKHa0cu3V0NXbJm2B4KEOt4QCDiFxUIX9z6eB4Kditwu05OgQh6KcogOiP\n'+'JesWxBMXXGoDC1rIYTFO7szwDyOHlCcVXJDNsTJhc32oDWYdeIbW7o/5I+aQsrXZ\n'+'C96HykZcgWzz6sElrQxUaT3IoMw/5nmw4uWKKnZnxgI9bY4fpQwMeBZ96iHfFxvH\n'+'mqfEEuC7uUoPofXdBp2ObQ==\n'+'-----END CERTIFICATE-----\n']};
-
-/***/ }),
-/* 35 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var Parser=__webpack_require__(36);var Sequences=__webpack_require__(41);var Packets=__webpack_require__(2);var Timers=__webpack_require__(78);var Stream=__webpack_require__(13).Stream;var Util=__webpack_require__(0);var PacketWriter=__webpack_require__(79);module.exports=Protocol;Util.inherits(Protocol,Stream);function Protocol(options){Stream.call(this);options=options||{};this.readable=true;this.writable=true;this._config=options.config||{};this._connection=options.connection;this._callback=null;this._fatalError=null;this._quitSequence=null;this._handshake=false;this._handshaked=false;this._ended=false;this._destroyed=false;this._queue=[];this._handshakeInitializationPacket=null;this._parser=new Parser({onError:this.handleParserError.bind(this),onPacket:this._parsePacket.bind(this),config:this._config});}Protocol.prototype.write=function(buffer){this._parser.write(buffer);return true;};Protocol.prototype.handshake=function handshake(options,callback){if(typeof options==='function'){callback=options;options={};}options=options||{};options.config=this._config;var sequence=this._enqueue(new Sequences.Handshake(options,callback));this._handshake=true;return sequence;};Protocol.prototype.query=function query(options,callback){return this._enqueue(new Sequences.Query(options,callback));};Protocol.prototype.changeUser=function changeUser(options,callback){return this._enqueue(new Sequences.ChangeUser(options,callback));};Protocol.prototype.ping=function ping(options,callback){if(typeof options==='function'){callback=options;options={};}return this._enqueue(new Sequences.Ping(options,callback));};Protocol.prototype.stats=function stats(options,callback){if(typeof options==='function'){callback=options;options={};}return this._enqueue(new Sequences.Statistics(options,callback));};Protocol.prototype.quit=function quit(options,callback){if(typeof options==='function'){callback=options;options={};}var self=this;var sequence=this._enqueue(new Sequences.Quit(options,callback));sequence.on('end',function(){self.end();});return this._quitSequence=sequence;};Protocol.prototype.end=function(){if(this._ended){return;}this._ended=true;if(this._quitSequence&&(this._quitSequence._ended||this._queue[0]===this._quitSequence)){this._quitSequence.end();this.emit('end');return;}var err=new Error('Connection lost: The server closed the connection.');err.fatal=true;err.code='PROTOCOL_CONNECTION_LOST';this._delegateError(err);};Protocol.prototype.pause=function(){this._parser.pause();var seq=this._queue[0];if(seq&&seq.emit){seq.emit('pause');}};Protocol.prototype.resume=function(){this._parser.resume();var seq=this._queue[0];if(seq&&seq.emit){seq.emit('resume');}};Protocol.prototype._enqueue=function(sequence){if(!this._validateEnqueue(sequence)){return sequence;}if(this._config.trace){sequence._callSite=sequence._callSite||new Error();}this._queue.push(sequence);this.emit('enqueue',sequence);var self=this;sequence.on('error',function(err){self._delegateError(err,sequence);}).on('packet',function(packet){Timers.active(sequence);self._emitPacket(packet);}).on('end',function(){self._dequeue(sequence);}).on('timeout',function(){var err=new Error(sequence.constructor.name+' inactivity timeout');err.code='PROTOCOL_SEQUENCE_TIMEOUT';err.fatal=true;err.timeout=sequence._timeout;self._delegateError(err,sequence);}).on('start-tls',function(){Timers.active(sequence);self._connection._startTLS(function(err){if(err){err.code='HANDSHAKE_SSL_ERROR';err.fatal=true;sequence.end(err);return;}Timers.active(sequence);sequence._tlsUpgradeCompleteHandler();});});if(this._queue.length===1){this._parser.resetPacketNumber();this._startSequence(sequence);}return sequence;};Protocol.prototype._validateEnqueue=function _validateEnqueue(sequence){var err;var prefix='Cannot enqueue '+sequence.constructor.name;if(this._fatalError){err=new Error(prefix+' after fatal error.');err.code='PROTOCOL_ENQUEUE_AFTER_FATAL_ERROR';}else if(this._quitSequence){err=new Error(prefix+' after invoking quit.');err.code='PROTOCOL_ENQUEUE_AFTER_QUIT';}else if(this._destroyed){err=new Error(prefix+' after being destroyed.');err.code='PROTOCOL_ENQUEUE_AFTER_DESTROY';}else if((this._handshake||this._handshaked)&&sequence.constructor===Sequences.Handshake){err=new Error(prefix+' after already enqueuing a Handshake.');err.code='PROTOCOL_ENQUEUE_HANDSHAKE_TWICE';}else{return true;}var self=this;err.fatal=false;sequence.on('error',function(err){self._delegateError(err,sequence);});process.nextTick(function(){sequence.end(err);});return false;};Protocol.prototype._parsePacket=function(){var sequence=this._queue[0];if(!sequence){var err=new Error('Received packet with no active sequence.');err.code='PROTOCOL_STRAY_PACKET';err.fatal=true;this._delegateError(err);return;}var Packet=this._determinePacket(sequence);var packet=new Packet({protocol41:this._config.protocol41});var packetName=Packet.name;if(Packet===Packets.RowDataPacket){sequence.RowDataPacket(packet,this._parser,this._connection);if(this._config.debug){this._debugPacket(true,packet);}return;}if(this._config.debug){this._parsePacketDebug(packet);}else{packet.parse(this._parser);}if(Packet===Packets.HandshakeInitializationPacket){this._handshakeInitializationPacket=packet;}Timers.active(sequence);if(!sequence[packetName]){var err=new Error('Received packet in the wrong sequence.');err.code='PROTOCOL_INCORRECT_PACKET_SEQUENCE';err.fatal=true;this._delegateError(err);return;}sequence[packetName](packet);};Protocol.prototype._parsePacketDebug=function _parsePacketDebug(packet){try{packet.parse(this._parser);}finally{this._debugPacket(true,packet);}};Protocol.prototype._emitPacket=function(packet){var packetWriter=new PacketWriter();packet.write(packetWriter);this.emit('data',packetWriter.toBuffer(this._parser));if(this._config.debug){this._debugPacket(false,packet);}};Protocol.prototype._determinePacket=function(sequence){var firstByte=this._parser.peak();if(sequence.determinePacket){var Packet=sequence.determinePacket(firstByte,this._parser);if(Packet){return Packet;}}switch(firstByte){case 0x00:if(!this._handshaked){this._handshaked=true;this.emit('handshake',this._handshakeInitializationPacket);}return Packets.OkPacket;case 0xfe:return Packets.EofPacket;case 0xff:return Packets.ErrorPacket;}throw new Error('Could not determine packet, firstByte = '+firstByte);};Protocol.prototype._dequeue=function(sequence){Timers.unenroll(sequence);if(this._fatalError){return;}this._queue.shift();var sequence=this._queue[0];if(!sequence){this.emit('drain');return;}this._parser.resetPacketNumber();this._startSequence(sequence);};Protocol.prototype._startSequence=function(sequence){if(sequence._timeout>0&&isFinite(sequence._timeout)){Timers.enroll(sequence,sequence._timeout);Timers.active(sequence);}if(sequence.constructor===Sequences.ChangeUser){sequence.start(this._handshakeInitializationPacket);}else{sequence.start();}};Protocol.prototype.handleNetworkError=function(err){err.fatal=true;var sequence=this._queue[0];if(sequence){sequence.end(err);}else{this._delegateError(err);}};Protocol.prototype.handleParserError=function handleParserError(err){var sequence=this._queue[0];if(sequence){sequence.end(err);}else{this._delegateError(err);}};Protocol.prototype._delegateError=function(err,sequence){if(this._fatalError){return;}if(err.fatal){this._fatalError=err;}if(this._shouldErrorBubbleUp(err,sequence)){this.emit('unhandledError',err);}else if(err.fatal){var queue=this._queue;process.nextTick(function(){queue.forEach(function(sequence){sequence.end(err);});queue.length=0;});}if(err.fatal){this.emit('end',err);}};Protocol.prototype._shouldErrorBubbleUp=function(err,sequence){if(sequence){if(sequence.hasErrorHandler()){return false;}else if(!err.fatal){return true;}}return err.fatal&&!this._hasPendingErrorHandlers();};Protocol.prototype._hasPendingErrorHandlers=function(){return this._queue.some(function(sequence){return sequence.hasErrorHandler();});};Protocol.prototype.destroy=function(){this._destroyed=true;this._parser.pause();if(this._connection.state!=='disconnected'){if(!this._ended){this.end();}}};Protocol.prototype._debugPacket=function(incoming,packet){var headline=incoming?'<-- ':'--> ';headline=headline+packet.constructor.name;if(Array.isArray(this._config.debug)&&this._config.debug.indexOf(packet.constructor.name)===-1){return;}console.log(headline);console.log(packet);console.log('');};
-
-/***/ }),
-/* 36 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var MAX_PACKET_LENGTH=Math.pow(2,24)-1;var MUL_32BIT=Math.pow(2,32);var PacketHeader=__webpack_require__(37);var BigNumber=__webpack_require__(38);var Buffer=__webpack_require__(1).Buffer;var BufferList=__webpack_require__(40);module.exports=Parser;function Parser(options){options=options||{};this._supportBigNumbers=options.config&&options.config.supportBigNumbers;this._buffer=Buffer.alloc(0);this._nextBuffers=new BufferList();this._longPacketBuffers=new BufferList();this._offset=0;this._packetEnd=null;this._packetHeader=null;this._packetOffset=null;this._onError=options.onError||function(err){throw err;};this._onPacket=options.onPacket||function(){};this._nextPacketNumber=0;this._encoding='utf-8';this._paused=false;}Parser.prototype.write=function write(chunk){this._nextBuffers.push(chunk);while(!this._paused){if(!this._packetHeader){if(!this._combineNextBuffers(4)){break;}this._packetHeader=new PacketHeader(this.parseUnsignedNumber(3),this.parseUnsignedNumber(1));if(this._packetHeader.number!==this._nextPacketNumber){var err=new Error('Packets out of order. Got: '+this._packetHeader.number+' '+'Expected: '+this._nextPacketNumber);err.code='PROTOCOL_PACKETS_OUT_OF_ORDER';err.fatal=true;this._onError(err);}this.incrementPacketNumber();}if(!this._combineNextBuffers(this._packetHeader.length)){break;}this._packetEnd=this._offset+this._packetHeader.length;this._packetOffset=this._offset;if(this._packetHeader.length===MAX_PACKET_LENGTH){this._longPacketBuffers.push(this._buffer.slice(this._packetOffset,this._packetEnd));this._advanceToNextPacket();continue;}this._combineLongPacketBuffers();var hadException=true;try{this._onPacket(this._packetHeader);hadException=false;}catch(err){if(!err||typeof err.code!=='string'||err.code.substr(0,7)!=='PARSER_'){throw err;}this._onError(err);hadException=false;}finally{this._advanceToNextPacket();if(hadException){process.nextTick(this.write.bind(this));}}}};Parser.prototype.append=function append(chunk){if(!chunk||chunk.length===0){return;}var sliceEnd=this._buffer.length;var sliceStart=this._packetOffset===null?this._offset:this._packetOffset;var sliceLength=sliceEnd-sliceStart;var buffer=null;var chunks=!(chunk instanceof Array||Array.isArray(chunk))?[chunk]:chunk;var length=0;var offset=0;for(var i=0;i1){buffer=Buffer.allocUnsafe(length);offset=0;for(var i=0;i4){var err=new Error('parseUnsignedNumber: Supports only up to 4 bytes');err.offset=this._offset-this._packetOffset-1;err.code='PARSER_UNSIGNED_TOO_LONG';throw err;}while(offset>=this._offset){value=(value<<8|buffer[offset])>>>0;offset--;}this._offset+=bytes;return value;};Parser.prototype.parseLengthCodedString=function(){var length=this.parseLengthCodedNumber();if(length===null){return null;}return this.parseString(length);};Parser.prototype.parseLengthCodedBuffer=function(){var length=this.parseLengthCodedNumber();if(length===null){return null;}return this.parseBuffer(length);};Parser.prototype.parseLengthCodedNumber=function parseLengthCodedNumber(){if(this._offset>=this._buffer.length){var err=new Error('Parser: read past end');err.offset=this._offset-this._packetOffset;err.code='PARSER_READ_PAST_END';throw err;}var bits=this._buffer[this._offset++];if(bits<=250){return bits;}switch(bits){case 251:return null;case 252:return this.parseUnsignedNumber(2);case 253:return this.parseUnsignedNumber(3);case 254:break;default:var err=new Error('Unexpected first byte'+(bits?': 0x'+bits.toString(16):''));err.offset=this._offset-this._packetOffset-1;err.code='PARSER_BAD_LENGTH_BYTE';throw err;}var low=this.parseUnsignedNumber(4);var high=this.parseUnsignedNumber(4);var value;if(high>>>21){value=new BigNumber(low).plus(new BigNumber(MUL_32BIT).times(high)).toString();if(this._supportBigNumbers){return value;}var err=new Error('parseLengthCodedNumber: JS precision range exceeded, '+'number is >= 53 bit: "'+value+'"');err.offset=this._offset-this._packetOffset-8;err.code='PARSER_JS_PRECISION_RANGE_EXCEEDED';throw err;}value=low+MUL_32BIT*high;return value;};Parser.prototype.parseFiller=function(length){return this.parseBuffer(length);};Parser.prototype.parseNullTerminatedBuffer=function(){var end=this._nullByteOffset();var value=this._buffer.slice(this._offset,end);this._offset=end+1;return value;};Parser.prototype.parseNullTerminatedString=function(){var end=this._nullByteOffset();var value=this._buffer.toString(this._encoding,this._offset,end);this._offset=end+1;return value;};Parser.prototype._nullByteOffset=function(){var offset=this._offset;while(this._buffer[offset]!==0x00){offset++;if(offset>=this._buffer.length){var err=new Error('Offset of null terminated string not found.');err.offset=this._offset-this._packetOffset;err.code='PARSER_MISSING_NULL_BYTE';throw err;}}return offset;};Parser.prototype.parsePacketTerminatedBuffer=function parsePacketTerminatedBuffer(){var length=this._packetEnd-this._offset;return this.parseBuffer(length);};Parser.prototype.parsePacketTerminatedString=function(){var length=this._packetEnd-this._offset;return this.parseString(length);};Parser.prototype.parseBuffer=function(length){var response=Buffer.alloc(length);this._buffer.copy(response,0,this._offset,this._offset+length);this._offset+=length;return response;};Parser.prototype.parseString=function(length){var offset=this._offset;var end=offset+length;var value=this._buffer.toString(this._encoding,offset,end);this._offset=end;return value;};Parser.prototype.parseGeometryValue=function(){var buffer=this.parseLengthCodedBuffer();var offset=4;if(buffer===null||!buffer.length){return null;}function parseGeometry(){var result=null;var byteOrder=buffer.readUInt8(offset);offset+=1;var wkbType=byteOrder?buffer.readUInt32LE(offset):buffer.readUInt32BE(offset);offset+=4;switch(wkbType){case 1:var x=byteOrder?buffer.readDoubleLE(offset):buffer.readDoubleBE(offset);offset+=8;var y=byteOrder?buffer.readDoubleLE(offset):buffer.readDoubleBE(offset);offset+=8;result={x:x,y:y};break;case 2:var numPoints=byteOrder?buffer.readUInt32LE(offset):buffer.readUInt32BE(offset);offset+=4;result=[];for(var i=numPoints;i>0;i--){var x=byteOrder?buffer.readDoubleLE(offset):buffer.readDoubleBE(offset);offset+=8;var y=byteOrder?buffer.readDoubleLE(offset):buffer.readDoubleBE(offset);offset+=8;result.push({x:x,y:y});}break;case 3:var numRings=byteOrder?buffer.readUInt32LE(offset):buffer.readUInt32BE(offset);offset+=4;result=[];for(var i=numRings;i>0;i--){var numPoints=byteOrder?buffer.readUInt32LE(offset):buffer.readUInt32BE(offset);offset+=4;var line=[];for(var j=numPoints;j>0;j--){var x=byteOrder?buffer.readDoubleLE(offset):buffer.readDoubleBE(offset);offset+=8;var y=byteOrder?buffer.readDoubleLE(offset):buffer.readDoubleBE(offset);offset+=8;line.push({x:x,y:y});}result.push(line);}break;case 4:case 5:case 6:case 7:var num=byteOrder?buffer.readUInt32LE(offset):buffer.readUInt32BE(offset);offset+=4;var result=[];for(var i=num;i>0;i--){result.push(parseGeometry());}break;}return result;}return parseGeometry();};Parser.prototype.reachedPacketEnd=function(){return this._offset===this._packetEnd;};Parser.prototype.incrementPacketNumber=function(){var currentPacketNumber=this._nextPacketNumber;this._nextPacketNumber=(this._nextPacketNumber+1)%256;return currentPacketNumber;};Parser.prototype.resetPacketNumber=function(){this._nextPacketNumber=0;};Parser.prototype.packetLength=function packetLength(){if(!this._packetHeader){return null;}return this._packetHeader.length+this._longPacketBuffers.size;};Parser.prototype._combineNextBuffers=function _combineNextBuffers(bytes){var length=this._buffer.length-this._offset;if(length>=bytes){return true;}if(length+this._nextBuffers.size0){var buffer=this._nextBuffers.shift();buffers.push(buffer);bytesNeeded-=buffer.length;}this.append(buffers);return true;};Parser.prototype._combineLongPacketBuffers=function _combineLongPacketBuffers(){if(!this._longPacketBuffers.size){return;}var remainingBytes=this._buffer.length-this._offset;var trailingPacketBytes=this._buffer.length-this._packetEnd;var buf=null;var buffer=Buffer.allocUnsafe(remainingBytes+this._longPacketBuffers.size);var offset=0;while(buf=this._longPacketBuffers.shift()){offset+=buf.copy(buffer,offset);}this._buffer.copy(buffer,offset,this._offset);this._buffer=buffer;this._offset=0;this._packetEnd=this._buffer.length-trailingPacketBytes;this._packetOffset=0;};Parser.prototype._advanceToNextPacket=function(){this._offset=this._packetEnd;this._packetHeader=null;this._packetEnd=null;this._packetOffset=null;};
-
-/***/ }),
-/* 37 */
-/***/ (function(module, exports) {
-
-module.exports=PacketHeader;function PacketHeader(length,number){this.length=length;this.number=number;}
-
-/***/ }),
-/* 38 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var __WEBPACK_AMD_DEFINE_RESULT__;;(function(globalObj){'use strict';var BigNumber,isNumeric=/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,mathceil=Math.ceil,mathfloor=Math.floor,notBool=' not a boolean or binary digit',roundingMode='rounding mode',tooManyDigits='number type has more than 15 significant digits',ALPHABET='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_',BASE=1e14,LOG_BASE=14,MAX_SAFE_INTEGER=0x1fffffffffffff,POWS_TEN=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],SQRT_BASE=1e7,MAX=1E9;function constructorFactory(config){var div,parseNumeric,id=0,P=BigNumber.prototype,ONE=new BigNumber(1),DECIMAL_PLACES=20,ROUNDING_MODE=4,TO_EXP_NEG=-7,TO_EXP_POS=21,MIN_EXP=-1e7,MAX_EXP=1e7,ERRORS=true,isValidInt=intValidatorWithErrors,CRYPTO=false,MODULO_MODE=1,POW_PRECISION=0,FORMAT={decimalSeparator:'.',groupSeparator:',',groupSize:3,secondaryGroupSize:0,fractionGroupSeparator:'\xA0',fractionGroupSize:0};function BigNumber(n,b){var c,e,i,num,len,str,x=this;if(!(x instanceof BigNumber)){if(ERRORS)raise(26,'constructor call without new',n);return new BigNumber(n,b);}if(b==null||!isValidInt(b,2,64,id,'base')){if(n instanceof BigNumber){x.s=n.s;x.e=n.e;x.c=(n=n.c)?n.slice():n;id=0;return;}if((num=typeof n=='number')&&n*0==0){x.s=1/n<0?(n=-n,-1):1;if(n===~~n){for(e=0,i=n;i>=10;i/=10,e++);x.e=e;x.c=[n];id=0;return;}str=n+'';}else{if(!isNumeric.test(str=n+''))return parseNumeric(x,str,num);x.s=str.charCodeAt(0)===45?(str=str.slice(1),-1):1;}}else{b=b|0;str=n+'';if(b==10){x=new BigNumber(n instanceof BigNumber?n:str);return round(x,DECIMAL_PLACES+x.e+1,ROUNDING_MODE);}if((num=typeof n=='number')&&n*0!=0||!new RegExp('^-?'+(c='['+ALPHABET.slice(0,b)+']+')+'(?:\\.'+c+')?$',b<37?'i':'').test(str)){return parseNumeric(x,str,num,b);}if(num){x.s=1/n<0?(str=str.slice(1),-1):1;if(ERRORS&&str.replace(/^0\.0*|\./,'').length>15){raise(id,tooManyDigits,n);}num=false;}else{x.s=str.charCodeAt(0)===45?(str=str.slice(1),-1):1;}str=convertBase(str,10,b,x.s);}if((e=str.indexOf('.'))>-1)str=str.replace('.','');if((i=str.search(/e/i))>0){if(e<0)e=i;e+=+str.slice(i+1);str=str.substring(0,i);}else if(e<0){e=str.length;}for(i=0;str.charCodeAt(i)===48;i++);for(len=str.length;str.charCodeAt(--len)===48;);str=str.slice(i,len+1);if(str){len=str.length;if(num&&ERRORS&&len>15&&(n>MAX_SAFE_INTEGER||n!==mathfloor(n))){raise(id,tooManyDigits,x.s*n);}e=e-i-1;if(e>MAX_EXP){x.c=x.e=null;}else if(ei)return(v=a[i++])!=null;};if(has(p='DECIMAL_PLACES')&&isValidInt(v,0,MAX,2,p)){DECIMAL_PLACES=v|0;}r[p]=DECIMAL_PLACES;if(has(p='ROUNDING_MODE')&&isValidInt(v,0,8,2,p)){ROUNDING_MODE=v|0;}r[p]=ROUNDING_MODE;if(has(p='EXPONENTIAL_AT')){if(isArray(v)){if(isValidInt(v[0],-MAX,0,2,p)&&isValidInt(v[1],0,MAX,2,p)){TO_EXP_NEG=v[0]|0;TO_EXP_POS=v[1]|0;}}else if(isValidInt(v,-MAX,MAX,2,p)){TO_EXP_NEG=-(TO_EXP_POS=(v<0?-v:v)|0);}}r[p]=[TO_EXP_NEG,TO_EXP_POS];if(has(p='RANGE')){if(isArray(v)){if(isValidInt(v[0],-MAX,-1,2,p)&&isValidInt(v[1],1,MAX,2,p)){MIN_EXP=v[0]|0;MAX_EXP=v[1]|0;}}else if(isValidInt(v,-MAX,MAX,2,p)){if(v|0)MIN_EXP=-(MAX_EXP=(v<0?-v:v)|0);else if(ERRORS)raise(2,p+' cannot be zero',v);}}r[p]=[MIN_EXP,MAX_EXP];if(has(p='ERRORS')){if(v===!!v||v===1||v===0){id=0;isValidInt=(ERRORS=!!v)?intValidatorWithErrors:intValidatorNoErrors;}else if(ERRORS){raise(2,p+notBool,v);}}r[p]=ERRORS;if(has(p='CRYPTO')){if(v===true||v===false||v===1||v===0){if(v){v=typeof crypto=='undefined';if(!v&&crypto&&(crypto.getRandomValues||crypto.randomBytes)){CRYPTO=true;}else if(ERRORS){raise(2,'crypto unavailable',v?void 0:crypto);}else{CRYPTO=false;}}else{CRYPTO=false;}}else if(ERRORS){raise(2,p+notBool,v);}}r[p]=CRYPTO;if(has(p='MODULO_MODE')&&isValidInt(v,0,9,2,p)){MODULO_MODE=v|0;}r[p]=MODULO_MODE;if(has(p='POW_PRECISION')&&isValidInt(v,0,MAX,2,p)){POW_PRECISION=v|0;}r[p]=POW_PRECISION;if(has(p='FORMAT')){if(typeof v=='object'){FORMAT=v;}else if(ERRORS){raise(2,p+' not an object',v);}}r[p]=FORMAT;return r;};BigNumber.max=function(){return maxOrMin(arguments,P.lt);};BigNumber.min=function(){return maxOrMin(arguments,P.gt);};BigNumber.random=function(){var pow2_53=0x20000000000000;var random53bitInt=Math.random()*pow2_53&0x1fffff?function(){return mathfloor(Math.random()*pow2_53);}:function(){return(Math.random()*0x40000000|0)*0x800000+(Math.random()*0x800000|0);};return function(dp){var a,b,e,k,v,i=0,c=[],rand=new BigNumber(ONE);dp=dp==null||!isValidInt(dp,0,MAX,14)?DECIMAL_PLACES:dp|0;k=mathceil(dp/LOG_BASE);if(CRYPTO){if(crypto.getRandomValues){a=crypto.getRandomValues(new Uint32Array(k*=2));for(;i>>11);if(v>=9e15){b=crypto.getRandomValues(new Uint32Array(2));a[i]=b[0];a[i+1]=b[1];}else{c.push(v%1e14);i+=2;}}i=k/2;}else if(crypto.randomBytes){a=crypto.randomBytes(k*=7);for(;i=9e15){crypto.randomBytes(7).copy(a,i);}else{c.push(v%1e14);i+=7;}}i=k/7;}else{CRYPTO=false;if(ERRORS)raise(14,'crypto unavailable',crypto);}}if(!CRYPTO){for(;i=10;v/=10,i++);if(i=0){k=POW_PRECISION;POW_PRECISION=0;str=str.replace('.','');y=new BigNumber(baseIn);x=y.pow(str.length-i);POW_PRECISION=k;y.c=toBaseOut(toFixedPoint(coeffToString(x.c),x.e),10,baseOut);y.e=y.c.length;}xc=toBaseOut(str,baseIn,baseOut);e=k=xc.length;for(;xc[--k]==0;xc.pop());if(!xc[0])return'0';if(i<0){--e;}else{x.c=xc;x.e=e;x.s=sign;x=div(x,y,dp,rm,baseOut);xc=x.c;r=x.r;e=x.e;}d=e+dp+1;i=xc[d];k=baseOut/2;r=r||d<0||xc[d+1]!=null;r=rm<4?(i!=null||r)&&(rm==0||rm==(x.s<0?3:2)):i>k||i==k&&(rm==4||r||rm==6&&xc[d-1]&1||rm==(x.s<0?8:7));if(d<1||!xc[0]){str=r?toFixedPoint('1',-dp):'0';}else{xc.length=d;if(r){for(--baseOut;++xc[--d]>baseOut;){xc[d]=0;if(!d){++e;xc=[1].concat(xc);}}}for(k=xc.length;!xc[--k];);for(i=0,str='';i<=k;str+=ALPHABET.charAt(xc[i++]));str=toFixedPoint(str,e);}return str;}div=function(){function multiply(x,k,base){var m,temp,xlo,xhi,carry=0,i=x.length,klo=k%SQRT_BASE,khi=k/SQRT_BASE|0;for(x=x.slice();i--;){xlo=x[i]%SQRT_BASE;xhi=x[i]/SQRT_BASE|0;m=khi*xlo+xhi*klo;temp=klo*xlo+m%SQRT_BASE*SQRT_BASE+carry;carry=(temp/base|0)+(m/SQRT_BASE|0)+khi*xhi;x[i]=temp%base;}if(carry)x=[carry].concat(x);return x;}function compare(a,b,aL,bL){var i,cmp;if(aL!=bL){cmp=aL>bL?1:-1;}else{for(i=cmp=0;ib[i]?1:-1;break;}}}return cmp;}function subtract(a,b,aL,base){var i=0;for(;aL--;){a[aL]-=i;i=a[aL]1;a.splice(0,1));}return function(x,y,dp,rm,base){var cmp,e,i,more,n,prod,prodL,q,qc,rem,remL,rem0,xi,xL,yc0,yL,yz,s=x.s==y.s?1:-1,xc=x.c,yc=y.c;if(!xc||!xc[0]||!yc||!yc[0]){return new BigNumber(!x.s||!y.s||(xc?yc&&xc[0]==yc[0]:!yc)?NaN:xc&&xc[0]==0||!yc?s*0:s/0);}q=new BigNumber(s);qc=q.c=[];e=x.e-y.e;s=dp+e+1;if(!base){base=BASE;e=bitFloor(x.e/LOG_BASE)-bitFloor(y.e/LOG_BASE);s=s/LOG_BASE|0;}for(i=0;yc[i]==(xc[i]||0);i++);if(yc[i]>(xc[i]||0))e--;if(s<0){qc.push(1);more=true;}else{xL=xc.length;yL=yc.length;i=0;s+=2;n=mathfloor(base/(yc[0]+1));if(n>1){yc=multiply(yc,n,base);xc=multiply(xc,n,base);yL=yc.length;xL=xc.length;}xi=yL;rem=xc.slice(0,yL);remL=rem.length;for(;remL=base/2)yc0++;do{n=0;cmp=compare(yc,rem,yL,remL);if(cmp<0){rem0=rem[0];if(yL!=remL)rem0=rem0*base+(rem[1]||0);n=mathfloor(rem0/yc0);if(n>1){if(n>=base)n=base-1;prod=multiply(yc,n,base);prodL=prod.length;remL=rem.length;while(compare(prod,rem,prodL,remL)==1){n--;subtract(prod,yL=10;s/=10,i++);round(q,dp+(q.e=i+e*LOG_BASE-1)+1,rm,more);}else{q.e=e;q.r=+more;}return q;};}();function format(n,i,rm,caller){var c0,e,ne,len,str;rm=rm!=null&&isValidInt(rm,0,8,caller,roundingMode)?rm|0:ROUNDING_MODE;if(!n.c)return n.toString();c0=n.c[0];ne=n.e;if(i==null){str=coeffToString(n.c);str=caller==19||caller==24&&ne<=TO_EXP_NEG?toExponential(str,ne):toFixedPoint(str,ne);}else{n=round(new BigNumber(n),i,rm);e=n.e;str=coeffToString(n.c);len=str.length;if(caller==19||caller==24&&(i<=e||e<=TO_EXP_NEG)){for(;lenlen){if(--i>0)for(str+='.';i--;str+='0');}else{i+=e-len;if(i>0){if(e+1==len)str+='.';for(;i--;str+='0');}}}}return n.s<0&&c0?'-'+str:str;}function maxOrMin(args,method){var m,n,i=0;if(isArray(args[0]))args=args[0];m=new BigNumber(args[0]);for(;++imax||n!=truncate(n)){raise(caller,(name||'decimal places')+(nmax?' out of range':' not an integer'),n);}return true;}function normalise(n,c,e){var i=1,j=c.length;for(;!c[--j];c.pop());for(j=c[0];j>=10;j/=10,i++);if((e=i+e*LOG_BASE-1)>MAX_EXP){n.c=n.e=null;}else if(e=10;k/=10,d++);i=sd-d;if(i<0){i+=LOG_BASE;j=sd;n=xc[ni=0];rd=n/pows10[d-j-1]%10|0;}else{ni=mathceil((i+1)/LOG_BASE);if(ni>=xc.length){if(r){for(;xc.length<=ni;xc.push(0));n=rd=0;d=1;i%=LOG_BASE;j=i-LOG_BASE+1;}else{break out;}}else{n=k=xc[ni];for(d=1;k>=10;k/=10,d++);i%=LOG_BASE;j=i-LOG_BASE+d;rd=j<0?0:n/pows10[d-j-1]%10|0;}}r=r||sd<0||xc[ni+1]!=null||(j<0?n:n%pows10[d-j-1]);r=rm<4?(rd||r)&&(rm==0||rm==(x.s<0?3:2)):rd>5||rd==5&&(rm==4||r||rm==6&&(i>0?j>0?n/pows10[d-j]:0:xc[ni-1])%10&1||rm==(x.s<0?8:7));if(sd<1||!xc[0]){xc.length=0;if(r){sd-=x.e+1;xc[0]=pows10[(LOG_BASE-sd%LOG_BASE)%LOG_BASE];x.e=-sd||0;}else{xc[0]=x.e=0;}return x;}if(i==0){xc.length=ni;k=1;ni--;}else{xc.length=ni+1;k=pows10[LOG_BASE-i];xc[ni]=j>0?mathfloor(n/pows10[d-j]%pows10[j])*k:0;}if(r){for(;;){if(ni==0){for(i=1,j=xc[0];j>=10;j/=10,i++);j=xc[0]+=k;for(k=1;j>=10;j/=10,k++);if(i!=k){x.e++;if(xc[0]==BASE)xc[0]=1;}break;}else{xc[ni]+=k;if(xc[ni]!=BASE)break;xc[ni--]=0;k=1;}}}for(i=xc.length;xc[--i]===0;xc.pop());}if(x.e>MAX_EXP){x.c=x.e=null;}else if(x.e0;};P.greaterThanOrEqualTo=P.gte=function(y,b){id=7;return(b=compare(this,new BigNumber(y,b)))===1||b===0;};P.isFinite=function(){return!!this.c;};P.isInteger=P.isInt=function(){return!!this.c&&bitFloor(this.e/LOG_BASE)>this.c.length-2;};P.isNaN=function(){return!this.s;};P.isNegative=P.isNeg=function(){return this.s<0;};P.isZero=function(){return!!this.c&&this.c[0]==0;};P.lessThan=P.lt=function(y,b){id=8;return compare(this,new BigNumber(y,b))<0;};P.lessThanOrEqualTo=P.lte=function(y,b){id=9;return(b=compare(this,new BigNumber(y,b)))===-1||b===0;};P.minus=P.sub=function(y,b){var i,j,t,xLTy,x=this,a=x.s;id=10;y=new BigNumber(y,b);b=y.s;if(!a||!b)return new BigNumber(NaN);if(a!=b){y.s=-b;return x.plus(y);}var xe=x.e/LOG_BASE,ye=y.e/LOG_BASE,xc=x.c,yc=y.c;if(!xe||!ye){if(!xc||!yc)return xc?(y.s=-b,y):new BigNumber(yc?x:NaN);if(!xc[0]||!yc[0]){return yc[0]?(y.s=-b,y):new BigNumber(xc[0]?x:ROUNDING_MODE==3?-0:0);}}xe=bitFloor(xe);ye=bitFloor(ye);xc=xc.slice();if(a=xe-ye){if(xLTy=a<0){a=-a;t=xc;}else{ye=xe;t=yc;}t.reverse();for(b=a;b--;t.push(0));t.reverse();}else{j=(xLTy=(a=xc.length)<(b=yc.length))?a:b;for(a=b=0;b0)for(;b--;xc[i++]=0);b=BASE-1;for(;j>a;){if(xc[--j]0){ye=xe;t=yc;}else{a=-a;t=xc;}t.reverse();for(;a--;t.push(0));t.reverse();}a=xc.length;b=yc.length;if(a-b<0)t=yc,yc=xc,xc=t,b=a;for(a=0;b;){a=(xc[--b]=xc[b]+yc[b]+a)/BASE|0;xc[b]=BASE===xc[b]?0:xc[b]%BASE;}if(a){xc=[a].concat(xc);++ye;}return normalise(y,xc,ye);};P.precision=P.sd=function(z){var n,v,x=this,c=x.c;if(z!=null&&z!==!!z&&z!==1&&z!==0){if(ERRORS)raise(13,'argument'+notBool,z);if(z!=!!z)z=null;}if(!c)return null;v=c.length-1;n=v*LOG_BASE+1;if(v=c[v]){for(;v%10==0;v/=10,n--);for(v=c[0];v>=10;v/=10,n++);}if(z&&x.e+1>n)n=x.e+1;return n;};P.round=function(dp,rm){var n=new BigNumber(this);if(dp==null||isValidInt(dp,0,MAX,15)){round(n,~~dp+this.e+1,rm==null||!isValidInt(rm,0,8,15,roundingMode)?ROUNDING_MODE:rm|0);}return n;};P.shift=function(k){var n=this;return isValidInt(k,-MAX_SAFE_INTEGER,MAX_SAFE_INTEGER,16,'argument')?n.times('1e'+truncate(k)):new BigNumber(n.c&&n.c[0]&&(k<-MAX_SAFE_INTEGER||k>MAX_SAFE_INTEGER)?n.s*(k<0?0:1/0):n);};P.squareRoot=P.sqrt=function(){var m,n,r,rep,t,x=this,c=x.c,s=x.s,e=x.e,dp=DECIMAL_PLACES+4,half=new BigNumber('0.5');if(s!==1||!c||!c[0]){return new BigNumber(!s||s<0&&(!c||c[0])?NaN:c?x:1/0);}s=Math.sqrt(+x);if(s==0||s==1/0){n=coeffToString(c);if((n.length+e)%2==0)n+='0';s=Math.sqrt(n);e=bitFloor((e+1)/2)-(e<0||e%2);if(s==1/0){n='1e'+e;}else{n=s.toExponential();n=n.slice(0,n.indexOf('e')+1)+e;}r=new BigNumber(n);}else{r=new BigNumber(s+'');}if(r.c[0]){e=r.e;s=e+dp;if(s<3)s=0;for(;;){t=r;r=half.times(t.plus(div(x,t,dp,1)));if(coeffToString(t.c).slice(0,s)===(n=coeffToString(r.c)).slice(0,s)){if(r.e=0;){c=0;ylo=yc[i]%sqrtBase;yhi=yc[i]/sqrtBase|0;for(k=xcL,j=i+k;j>i;){xlo=xc[--k]%sqrtBase;xhi=xc[k]/sqrtBase|0;m=yhi*xlo+xhi*ylo;xlo=ylo*xlo+m%sqrtBase*sqrtBase+zc[j]+c;c=(xlo/base|0)+(m/sqrtBase|0)+yhi*xhi;zc[j--]=xlo%base;}zc[j]=c;}if(c){++e;}else{zc.splice(0,1);}return normalise(y,zc,e);};P.toDigits=function(sd,rm){var n=new BigNumber(this);sd=sd==null||!isValidInt(sd,1,MAX,18,'precision')?null:sd|0;rm=rm==null||!isValidInt(rm,0,8,18,roundingMode)?ROUNDING_MODE:rm|0;return sd?round(n,sd,rm):n;};P.toExponential=function(dp,rm){return format(this,dp!=null&&isValidInt(dp,0,MAX,19)?~~dp+1:null,rm,19);};P.toFixed=function(dp,rm){return format(this,dp!=null&&isValidInt(dp,0,MAX,20)?~~dp+this.e+1:null,rm,20);};P.toFormat=function(dp,rm){var str=format(this,dp!=null&&isValidInt(dp,0,MAX,21)?~~dp+this.e+1:null,rm,21);if(this.c){var i,arr=str.split('.'),g1=+FORMAT.groupSize,g2=+FORMAT.secondaryGroupSize,groupSeparator=FORMAT.groupSeparator,intPart=arr[0],fractionPart=arr[1],isNeg=this.s<0,intDigits=isNeg?intPart.slice(1):intPart,len=intDigits.length;if(g2)i=g1,g1=g2,g2=i,len-=i;if(g1>0&&len>0){i=len%g1||g1;intPart=intDigits.substr(0,i);for(;i0)intPart+=groupSeparator+intDigits.slice(i);if(isNeg)intPart='-'+intPart;}str=fractionPart?intPart+FORMAT.decimalSeparator+((g2=+FORMAT.fractionGroupSize)?fractionPart.replace(new RegExp('\\d{'+g2+'}\\B','g'),'$&'+FORMAT.fractionGroupSeparator):fractionPart):intPart;}return str;};P.toFraction=function(md){var arr,d0,d2,e,exp,n,n0,q,s,k=ERRORS,x=this,xc=x.c,d=new BigNumber(ONE),n1=d0=new BigNumber(ONE),d1=n0=new BigNumber(ONE);if(md!=null){ERRORS=false;n=new BigNumber(md);ERRORS=k;if(!(k=n.isInt())||n.lt(ONE)){if(ERRORS){raise(22,'max denominator '+(k?'out of range':'not an integer'),md);}md=!k&&n.c&&round(n,n.e+1,1).gte(ONE)?n:null;}}if(!xc)return x.toString();s=coeffToString(xc);e=d.e=s.length-x.e-1;d.c[0]=POWS_TEN[(exp=e%LOG_BASE)<0?LOG_BASE+exp:exp];md=!md||n.cmp(d)>0?e>0?d:n1:n;exp=MAX_EXP;MAX_EXP=1/0;n=new BigNumber(s);n0.c[0]=0;for(;;){q=div(n,d,0,1);d2=d0.plus(q.times(d1));if(d2.cmp(md)==1)break;d0=d1;d1=d2;n1=n0.plus(q.times(d2=n1));n0=d2;d=n.minus(q.times(d2=d));n=d2;}d2=div(md.minus(d0),d1,0,1);n0=n0.plus(d2.times(n1));d0=d0.plus(d2.times(d1));n0.s=n1.s=x.s;e*=2;arr=div(n1,d1,e,ROUNDING_MODE).minus(x).abs().cmp(div(n0,d0,e,ROUNDING_MODE).minus(x).abs())<1?[n1.toString(),d1.toString()]:[n0.toString(),d0.toString()];MAX_EXP=exp;return arr;};P.toNumber=function(){return+this;};P.toPower=P.pow=function(n,m){var k,y,z,i=mathfloor(n<0?-n:+n),x=this;if(m!=null){id=23;m=new BigNumber(m);}if(!isValidInt(n,-MAX_SAFE_INTEGER,MAX_SAFE_INTEGER,23,'exponent')&&(!isFinite(n)||i>MAX_SAFE_INTEGER&&(n/=0)||parseFloat(n)!=n&&!(n=NaN))||n==0){k=Math.pow(+x,n);return new BigNumber(m?k%m:k);}if(m){if(n>1&&x.gt(ONE)&&x.isInt()&&m.gt(ONE)&&m.isInt()){x=x.mod(m);}else{z=m;m=null;}}else if(POW_PRECISION){k=mathceil(POW_PRECISION/LOG_BASE+2);}y=new BigNumber(ONE);for(;;){if(i%2){y=y.times(x);if(!y.c)break;if(k){if(y.c.length>k)y.c.length=k;}else if(m){y=y.mod(m);}}i=mathfloor(i/2);if(!i)break;x=x.times(x);if(k){if(x.c&&x.c.length>k)x.c.length=k;}else if(m){x=x.mod(m);}}if(m)return y;if(n<0)y=ONE.div(y);return z?y.mod(z):k?round(y,POW_PRECISION,ROUNDING_MODE):y;};P.toPrecision=function(sd,rm){return format(this,sd!=null&&isValidInt(sd,1,MAX,24,'precision')?sd|0:null,rm,24);};P.toString=function(b){var str,n=this,s=n.s,e=n.e;if(e===null){if(s){str='Infinity';if(s<0)str='-'+str;}else{str='NaN';}}else{str=coeffToString(n.c);if(b==null||!isValidInt(b,2,64,25,'base')){str=e<=TO_EXP_NEG||e>=TO_EXP_POS?toExponential(str,e):toFixedPoint(str,e);}else{str=convertBase(toFixedPoint(str,e),b|0,10,s);}if(s<0&&n.c[0])str='-'+str;}return str;};P.truncated=P.trunc=function(){return round(new BigNumber(this),this.e+1,1);};P.valueOf=P.toJSON=function(){var str,n=this,e=n.e;if(e===null)return n.toString();str=coeffToString(n.c);str=e<=TO_EXP_NEG||e>=TO_EXP_POS?toExponential(str,e):toFixedPoint(str,e);return n.s<0?'-'+str:str;};P.isBigNumber=true;if(config!=null)BigNumber.config(config);return BigNumber;}function bitFloor(n){var i=n|0;return n>0||n===i?i:i-1;}function coeffToString(a){var s,z,i=1,j=a.length,r=a[0]+'';for(;il^a?1:-1;j=(k=xc.length)<(l=yc.length)?k:l;for(i=0;iyc[i]^a?1:-1;return k==l?0:k>l^a?1:-1;}function intValidatorNoErrors(n,min,max){return(n=truncate(n))>=min&&n<=max;}function isArray(obj){return Object.prototype.toString.call(obj)=='[object Array]';}function toBaseOut(str,baseIn,baseOut){var j,arr=[0],arrL,i=0,len=str.length;for(;ibaseOut-1){if(arr[j+1]==null)arr[j+1]=0;arr[j+1]+=arr[j]/baseOut|0;arr[j]%=baseOut;}}}return arr.reverse();}function toExponential(str,e){return(str.length>1?str.charAt(0)+'.'+str.slice(1):str)+(e<0?'e':'e+')+e;}function toFixedPoint(str,e){var len,z;if(e<0){for(z='0.';++e;z+='0');str=z+str;}else{len=str.length;if(++e>len){for(z='0',e-=len;--e;z+='0');str+=z;}else if(e0;if(this.protocol41){this.serverCapabilities2=parser.parseUnsignedNumber(2);this.scrambleLength=parser.parseUnsignedNumber(1);this.filler2=parser.parseFiller(10);this.scrambleBuff2=parser.parseBuffer(12);this.filler3=parser.parseFiller(1);}else{this.filler2=parser.parseFiller(13);}if(parser.reachedPacketEnd()){return;}this.pluginData=parser.parsePacketTerminatedString();var lastChar=this.pluginData.length-1;if(this.pluginData[lastChar]==='\0'){this.pluginData=this.pluginData.substr(0,lastChar);}};HandshakeInitializationPacket.prototype.write=function(writer){writer.writeUnsignedNumber(1,this.protocolVersion);writer.writeNullTerminatedString(this.serverVersion);writer.writeUnsignedNumber(4,this.threadId);writer.writeBuffer(this.scrambleBuff1);writer.writeFiller(1);writer.writeUnsignedNumber(2,this.serverCapabilities1);writer.writeUnsignedNumber(1,this.serverLanguage);writer.writeUnsignedNumber(2,this.serverStatus);if(this.protocol41){writer.writeUnsignedNumber(2,this.serverCapabilities2);writer.writeUnsignedNumber(1,this.scrambleLength);writer.writeFiller(10);}writer.writeNullTerminatedBuffer(this.scrambleBuff2);if(this.pluginData!==undefined){writer.writeNullTerminatedString(this.pluginData);}};HandshakeInitializationPacket.prototype.scrambleBuff=function(){var buffer=null;if(typeof this.scrambleBuff2==='undefined'){buffer=Buffer.from(this.scrambleBuff1);}else{buffer=Buffer.allocUnsafe(this.scrambleBuff1.length+this.scrambleBuff2.length);this.scrambleBuff1.copy(buffer,0);this.scrambleBuff2.copy(buffer,this.scrambleBuff1.length);}return buffer;};
-
-/***/ }),
-/* 56 */
-/***/ (function(module, exports) {
-
-module.exports=LocalDataFilePacket;function LocalDataFilePacket(data){this.data=data;}LocalDataFilePacket.prototype.write=function(writer){writer.writeBuffer(this.data);};
-
-/***/ }),
-/* 57 */
-/***/ (function(module, exports) {
-
-var ER_UPDATE_INFO_REGEXP=/^[^:0-9]+: [0-9]+[^:0-9]+: ([0-9]+)[^:0-9]+: [0-9]+[^:0-9]*$/;module.exports=OkPacket;function OkPacket(options){options=options||{};this.fieldCount=undefined;this.affectedRows=undefined;this.insertId=undefined;this.serverStatus=undefined;this.warningCount=undefined;this.message=undefined;this.protocol41=options.protocol41;}OkPacket.prototype.parse=function(parser){this.fieldCount=parser.parseUnsignedNumber(1);this.affectedRows=parser.parseLengthCodedNumber();this.insertId=parser.parseLengthCodedNumber();if(this.protocol41){this.serverStatus=parser.parseUnsignedNumber(2);this.warningCount=parser.parseUnsignedNumber(2);}this.message=parser.parsePacketTerminatedString();this.changedRows=0;var m=ER_UPDATE_INFO_REGEXP.exec(this.message);if(m!==null){this.changedRows=parseInt(m[1],10);}};OkPacket.prototype.write=function(writer){writer.writeUnsignedNumber(1,0x00);writer.writeLengthCodedNumber(this.affectedRows||0);writer.writeLengthCodedNumber(this.insertId||0);if(this.protocol41){writer.writeUnsignedNumber(2,this.serverStatus||0);writer.writeUnsignedNumber(2,this.warningCount||0);}writer.writeString(this.message);};
-
-/***/ }),
-/* 58 */
-/***/ (function(module, exports) {
-
-module.exports=OldPasswordPacket;function OldPasswordPacket(options){options=options||{};this.scrambleBuff=options.scrambleBuff;}OldPasswordPacket.prototype.parse=function(parser){this.scrambleBuff=parser.parseNullTerminatedBuffer();};OldPasswordPacket.prototype.write=function(writer){writer.writeBuffer(this.scrambleBuff);writer.writeFiller(1);};
-
-/***/ }),
-/* 59 */
-/***/ (function(module, exports) {
-
-module.exports=ResultSetHeaderPacket;function ResultSetHeaderPacket(options){options=options||{};this.fieldCount=options.fieldCount;this.extra=options.extra;}ResultSetHeaderPacket.prototype.parse=function(parser){this.fieldCount=parser.parseLengthCodedNumber();if(parser.reachedPacketEnd())return;this.extra=this.fieldCount===null?parser.parsePacketTerminatedString():parser.parseLengthCodedNumber();};ResultSetHeaderPacket.prototype.write=function(writer){writer.writeLengthCodedNumber(this.fieldCount);if(this.extra!==undefined){writer.writeLengthCodedNumber(this.extra);}};
-
-/***/ }),
-/* 60 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var Types=__webpack_require__(12);var Charsets=__webpack_require__(16);var Field=__webpack_require__(17);var IEEE_754_BINARY_64_PRECISION=Math.pow(2,53);module.exports=RowDataPacket;function RowDataPacket(){}Object.defineProperty(RowDataPacket.prototype,'parse',{configurable:true,enumerable:false,value:parse});Object.defineProperty(RowDataPacket.prototype,'_typeCast',{configurable:true,enumerable:false,value:typeCast});function parse(parser,fieldPackets,typeCast,nestTables,connection){var self=this;var next=function(){return self._typeCast(fieldPacket,parser,connection.config.timezone,connection.config.supportBigNumbers,connection.config.bigNumberStrings,connection.config.dateStrings);};for(var i=0;i=IEEE_754_BINARY_64_PRECISION||Number(numberString)<=-IEEE_754_BINARY_64_PRECISION)?numberString:Number(numberString);case Types.BIT:return parser.parseLengthCodedBuffer();case Types.STRING:case Types.VAR_STRING:case Types.TINY_BLOB:case Types.MEDIUM_BLOB:case Types.LONG_BLOB:case Types.BLOB:return field.charsetNr===Charsets.BINARY?parser.parseLengthCodedBuffer():parser.parseLengthCodedString();case Types.GEOMETRY:return parser.parseGeometryValue();default:return parser.parseLengthCodedString();}}function typeMatch(type,list){if(Array.isArray(list)){for(var i=0;i0)this.tail.next=entry;else this.head=entry;this.tail=entry;++this.length;};BufferList.prototype.unshift=function unshift(v){var entry={data:v,next:this.head};if(this.length===0)this.tail=entry;this.head=entry;++this.length;};BufferList.prototype.shift=function shift(){if(this.length===0)return;var ret=this.head.data;if(this.length===1)this.head=this.tail=null;else this.head=this.head.next;--this.length;return ret;};BufferList.prototype.clear=function clear(){this.head=this.tail=null;this.length=0;};BufferList.prototype.join=function join(s){if(this.length===0)return'';var p=this.head;var ret=''+p.data;while(p=p.next){ret+=s+p.data;}return ret;};BufferList.prototype.concat=function concat(n){if(this.length===0)return Buffer.alloc(0);if(this.length===1)return this.head.data;var ret=Buffer.allocUnsafe(n>>>0);var p=this.head;var i=0;while(p){copyBuffer(p.data,ret,i);i+=p.data.length;p=p.next;}return ret;};return BufferList;}();
-
-/***/ }),
-/* 74 */
-/***/ (function(module, exports, __webpack_require__) {
-
-module.exports=__webpack_require__(0).deprecate;
-
-/***/ }),
-/* 75 */
-/***/ (function(module, exports, __webpack_require__) {
-
-"use strict";
-module.exports=PassThrough;var Transform=__webpack_require__(25);var util=__webpack_require__(6);util.inherits=__webpack_require__(7);util.inherits(PassThrough,Transform);function PassThrough(options){if(!(this instanceof PassThrough))return new PassThrough(options);Transform.call(this,options);}PassThrough.prototype._transform=function(chunk,encoding,cb){cb(null,chunk);};
-
-/***/ }),
-/* 76 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var Sequence=__webpack_require__(3);var Util=__webpack_require__(0);var Packets=__webpack_require__(2);module.exports=Quit;Util.inherits(Quit,Sequence);function Quit(options,callback){if(!callback&&typeof options==='function'){callback=options;options={};}Sequence.call(this,options,callback);this._started=false;}Quit.prototype.end=function end(err){if(this._ended){return;}if(!this._started){Sequence.prototype.end.call(this,err);return;}if(err&&err.code==='ECONNRESET'&&err.syscall==='read'){Sequence.prototype.end.call(this);return;}Sequence.prototype.end.call(this,err);};Quit.prototype.start=function(){this._started=true;this.emit('packet',new Packets.ComQuitPacket());};
-
-/***/ }),
-/* 77 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var Sequence=__webpack_require__(3);var Util=__webpack_require__(0);var Packets=__webpack_require__(2);module.exports=Statistics;Util.inherits(Statistics,Sequence);function Statistics(options,callback){if(!callback&&typeof options==='function'){callback=options;options={};}Sequence.call(this,options,callback);}Statistics.prototype.start=function(){this.emit('packet',new Packets.ComStatisticsPacket());};Statistics.prototype['StatisticsPacket']=function(packet){this.end(null,packet);};Statistics.prototype.determinePacket=function determinePacket(firstByte){if(firstByte===0x55){return Packets.StatisticsPacket;}return undefined;};
-
-/***/ }),
-/* 78 */
-/***/ (function(module, exports) {
-
-module.exports = require("timers");
-
-/***/ }),
-/* 79 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var BIT_16=Math.pow(2,16);var BIT_24=Math.pow(2,24);var BUFFER_ALLOC_SIZE=Math.pow(2,8);var IEEE_754_BINARY_64_PRECISION=Math.pow(2,53);var MAX_PACKET_LENGTH=Math.pow(2,24)-1;var Buffer=__webpack_require__(1).Buffer;module.exports=PacketWriter;function PacketWriter(){this._buffer=null;this._offset=0;}PacketWriter.prototype.toBuffer=function toBuffer(parser){if(!this._buffer){this._buffer=Buffer.alloc(0);this._offset=0;}var buffer=this._buffer;var length=this._offset;var packets=Math.floor(length/MAX_PACKET_LENGTH)+1;this._buffer=Buffer.allocUnsafe(length+packets*4);this._offset=0;for(var packet=0;packet>i*8&0xff;}};PacketWriter.prototype.writeFiller=function(bytes){this._allocate(bytes);for(var i=0;iIEEE_754_BINARY_64_PRECISION){throw new Error('writeLengthCodedNumber: JS precision range exceeded, your '+'number is > 53 bit: "'+value+'"');}if(value>8&0xff;if(value>16&0xff;if(value>24&0xff;value=value.toString(2);value=value.substr(0,value.length-32);value=parseInt(value,2);this._buffer[this._offset++]=value&0xff;this._buffer[this._offset++]=value>>8&0xff;this._buffer[this._offset++]=value>>16&0xff;this._buffer[this._offset++]=0;};PacketWriter.prototype.writeLengthCodedBuffer=function(value){var bytes=value.length;this.writeLengthCodedNumber(bytes);this.writeBuffer(value);};PacketWriter.prototype.writeNullTerminatedBuffer=function(value){this.writeBuffer(value);this.writeFiller(1);};PacketWriter.prototype.writeLengthCodedString=function(value){if(value===null){this.writeLengthCodedNumber(null);return;}value=value===undefined?'':String(value);var bytes=Buffer.byteLength(value,'utf-8');this.writeLengthCodedNumber(bytes);if(!bytes){return;}this._allocate(bytes);this._buffer.write(value,this._offset,'utf-8');this._offset+=bytes;};PacketWriter.prototype._allocate=function _allocate(bytes){if(!this._buffer){this._buffer=Buffer.alloc(Math.max(BUFFER_ALLOC_SIZE,bytes));this._offset=0;return;}var bytesRemaining=this._buffer.length-this._offset;if(bytesRemaining>=bytes){return;}var newSize=this._buffer.length+Math.max(BUFFER_ALLOC_SIZE,bytes);var oldBuffer=this._buffer;this._buffer=Buffer.alloc(newSize);oldBuffer.copy(this._buffer);};
-
-/***/ }),
-/* 80 */
-/***/ (function(module, exports, __webpack_require__) {
-
-module.exports=__webpack_require__(81);
-
-/***/ }),
-/* 81 */
-/***/ (function(module, exports) {
-
-var SqlString=exports;var ID_GLOBAL_REGEXP=/`/g;var QUAL_GLOBAL_REGEXP=/\./g;var CHARS_GLOBAL_REGEXP=/[\0\b\t\n\r\x1a\"\'\\]/g;var CHARS_ESCAPE_MAP={'\0':'\\0','\b':'\\b','\t':'\\t','\n':'\\n','\r':'\\r','\x1a':'\\Z','"':'\\"','\'':'\\\'','\\':'\\\\'};SqlString.escapeId=function escapeId(val,forbidQualified){if(Array.isArray(val)){var sql='';for(var i=0;ithis._removeNodeErrorCount){errorCount=this._removeNodeErrorCount;}if(errorCount<1){errorCount=1;}node.errorCount=errorCount-1;if(node._offlineUntil){node._offlineUntil=0;this.emit('online',node.id);}};PoolCluster.prototype._findNodeIds=function _findNodeIds(pattern,includeOffline){var currentTime=0;var foundNodeIds=this._findCaches[pattern];if(foundNodeIds===undefined){var expression=patternRegExp(pattern);var nodeIds=Object.keys(this._nodes);foundNodeIds=nodeIds.filter(function(id){return id.match(expression);});this._findCaches[pattern]=foundNodeIds;}if(includeOffline){return foundNodeIds;}return foundNodeIds.filter(function(nodeId){var node=this._getNode(nodeId);if(!node._offlineUntil){return true;}if(!currentTime){currentTime=getMonotonicMilliseconds();}return node._offlineUntil<=currentTime;},this);};PoolCluster.prototype._getNode=function _getNode(id){return this._nodes[id]||null;};PoolCluster.prototype._increaseErrorCount=function _increaseErrorCount(node){var errorCount=++node.errorCount;if(this._removeNodeErrorCount>errorCount){return;}if(this._restoreNodeTimeout>0){node._offlineUntil=getMonotonicMilliseconds()+this._restoreNodeTimeout;this.emit('offline',node.id);return;}this._removeNode(node);this.emit('remove',node.id);};PoolCluster.prototype._getConnection=function(node,cb){var self=this;node.pool.getConnection(function(err,connection){if(err){self._increaseErrorCount(node);cb(err);return;}else{self._decreaseErrorCount(node);}connection._clusterId=node.id;cb(null,connection);});};PoolCluster.prototype._removeNode=function _removeNode(node){delete this._nodes[node.id];this._clearFindCaches();node.pool.end(_noop);};function getMonotonicMilliseconds(){var ms;if(typeof process.hrtime==='function'){ms=process.hrtime();ms=ms[0]*1e3+ms[1]*1e-6;}else{ms=process.uptime()*1000;}return Math.floor(ms);}function isRegExp(val){return typeof val==='object'&&Object.prototype.toString.call(val)==='[object RegExp]';}function patternRegExp(pattern){if(isRegExp(pattern)){return pattern;}var source=pattern.replace(/([.+?^=!:${}()|\[\]\/\\])/g,'\\$1').replace(/\*/g,'.*');return new RegExp('^'+source+'$');}function _cb(err){if(err){throw err;}}function _noop(){}
-
-/***/ }),
-/* 84 */
-/***/ (function(module, exports, __webpack_require__) {
-
-var Connection=__webpack_require__(8);var PoolSelector=__webpack_require__(29);module.exports=PoolNamespace;function PoolNamespace(cluster,pattern,selector){this._cluster=cluster;this._pattern=pattern;this._selector=new PoolSelector[selector]();}PoolNamespace.prototype.getConnection=function(cb){var clusterNode=this._getClusterNode();var cluster=this._cluster;var namespace=this;if(clusterNode===null){var err=null;if(this._cluster._findNodeIds(this._pattern,true).length!==0){err=new Error('Pool does not have online node.');err.code='POOL_NONEONLINE';}else{err=new Error('Pool does not exist.');err.code='POOL_NOEXIST';}cb(err);return;}cluster._getConnection(clusterNode,function(err,connection){var retry=err&&cluster._canRetry&&cluster._findNodeIds(namespace._pattern).length!==0;if(retry){namespace.getConnection(cb);return;}if(err){cb(err);return;}cb(null,connection);});};PoolNamespace.prototype.query=function(sql,values,cb){var cluster=this._cluster;var clusterNode=this._getClusterNode();var query=Connection.createQuery(sql,values,cb);var namespace=this;if(clusterNode===null){var err=null;if(this._cluster._findNodeIds(this._pattern,true).length!==0){err=new Error('Pool does not have online node.');err.code='POOL_NONEONLINE';}else{err=new Error('Pool does not exist.');err.code='POOL_NOEXIST';}process.nextTick(function(){query.on('error',function(){});query.end(err);});return query;}if(!(typeof sql==='object'&&'typeCast'in sql)){query.typeCast=clusterNode.pool.config.connectionConfig.typeCast;}if(clusterNode.pool.config.connectionConfig.trace){query._callSite=new Error();}cluster._getConnection(clusterNode,function(err,conn){var retry=err&&cluster._canRetry&&cluster._findNodeIds(namespace._pattern).length!==0;if(retry){namespace.query(query);return;}if(err){query.on('error',function(){});query.end(err);return;}query.once('end',function(){conn.release();});conn.query(query);});return query;};PoolNamespace.prototype._getClusterNode=function _getClusterNode(){var foundNodeIds=this._cluster._findNodeIds(this._pattern);var nodeId;switch(foundNodeIds.length){case 0:nodeId=null;break;case 1:nodeId=foundNodeIds[0];break;default:nodeId=this._selector(foundNodeIds);break;}return nodeId!==null?this._cluster._getNode(nodeId):null;};
-
-/***/ })
-/******/ ]);
\ No newline at end of file
diff --git a/resources/ghmattimysql/ghmattimysql.lua b/resources/ghmattimysql/ghmattimysql.lua
deleted file mode 100644
index b9fa2d817..000000000
--- a/resources/ghmattimysql/ghmattimysql.lua
+++ /dev/null
@@ -1,39 +0,0 @@
-local function safeParameters(parameters)
- if parameters == nil then
- return {[''] = ''}
- end
- return parameters
-end
-
-exports('executeSync', function (query, parameters)
- local res = {}
- local finishedQuery = false
- exports.ghmattimysql:execute(query, safeParameters(parameters), function (result)
- res = result
- finishedQuery = true
- end)
- repeat Citizen.Wait(0) until finishedQuery == true
- return res
-end)
-
-exports('scalarSync', function (query, parameters)
- local res = {}
- local finishedQuery = false
- exports.ghmattimysql:scalar(query, safeParameters(parameters), function (result)
- res = result
- finishedQuery = true
- end)
- repeat Citizen.Wait(0) until finishedQuery == true
- return res
-end)
-
-exports('transactionSync', function (query, parameters)
- local res = {}
- local finishedTransaction = false
- exports.ghmattimysql:transaction(query, safeParameters(parameters), function (result)
- res = result
- finishedTransaction = true
- end)
- repeat Citizen.Wait(0) until finishedTransaction == true
- return res
-end)
diff --git a/resources/police/client/armory.lua b/resources/police/client/armory.lua
deleted file mode 100644
index 7be3b67ee..000000000
--- a/resources/police/client/armory.lua
+++ /dev/null
@@ -1,164 +0,0 @@
---[[
- Cops_FiveM - A cops script for FiveM RP servers.
- Copyright (C) 2018 FiveM-Scripts
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero 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 Affero General Public License for more details.
-You should have received a copy of the GNU Affero General Public License
-along with Cops_FiveM in the file "LICENSE". If not, see .
-]]
-
-local buttonsCategories = {}
-local buttonWeaponList = {}
-
-function load_armory()
- for k in ipairs (buttonsCategories) do
- buttonsCategories [k] = nil
- end
-
- for k in ipairs (buttonWeaponList) do
- buttonWeaponList [k] = nil
- end
-
- buttonsCategories[#buttonsCategories+1] = {name = i18n.translate("armory_basic_kit"), func = "giveBasicKit", params = ""}
- if config.enableOutfits then
- buttonsCategories[#buttonsCategories+1] = {name = i18n.translate("armory_add_bulletproof_vest_title"), func = "addBulletproofVest", params = ""}
- buttonsCategories[#buttonsCategories+1] = {name = i18n.translate("armory_remove_bulletproof_vest_title"), func = "removeBulletproofVest", params = ""}
- end
- buttonsCategories[#buttonsCategories+1] = {name = i18n.translate("armory_weapons_list"), func = "openWeaponListMenu", params = ""}
-
- buttonsCategories[#buttonsCategories+1] = {name = "Close", func = "CloseArmory", params = ""}
-
- for k,v in pairs(weapons) do
- buttonWeaponList[#buttonWeaponList+1] = {name = tostring(v.name), func = 'GiveCustomWeapon', params = tostring(v.hash)}
- end
-end
-
-local hashSkin = GetHashKey("mp_m_freemode_01")
-
-function createArmoryPed()
- if not DoesEntityExist(armoryPed) then
- local model = GetHashKey("s_m_y_cop_01")
-
- RequestModel(model)
- while not HasModelLoaded(model) do
- Wait(0)
- end
-
- local armoryPed = CreatePed(26, model, 454.165, -979.999, 30.690, 92.298, false, false)
- SetEntityInvincible(armoryPed, true)
- TaskTurnPedToFaceEntity(armoryPed, PlayerId(), -1)
-
- return armoryPed
- end
-end
-
-function giveBasicKit()
- for k,v in pairs(basic_kit) do
- GiveWeaponToPed(PlayerPedId(), GetHashKey(v), -1, true, false)
- end
-
- SetCurrentPedWeapon(PlayerPedId(), GetHashKey("WEAPON_UNARMED"), true)
- PlaySoundFrontend(-1, "PICK_UP", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
-end
-
-function giveBasicPrisonKit()
- GiveWeaponToPed(PlayerPedId(), GetHashKey("WEAPON_PISTOL50"), -1, true, true)
- GiveWeaponToPed(PlayerPedId(), GetHashKey("WEAPON_STUNGUN"), -1, true, true)
- GiveWeaponToPed(PlayerPedId(), GetHashKey("WEAPON_NIGHTSTICK"), 200, true, true)
- GiveWeaponToPed(PlayerPedId(), GetHashKey("WEAPON_FLASHLIGHT"), 200, true, true)
-
- PlaySoundFrontend(-1, "PICK_UP", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
-end
-
-function addBulletproofVest()
- if(config.enableOutfits == true) then
- if(GetEntityModel(PlayerPedId()) == hashSkin) then
- SetPedComponentVariation(PlayerPedId(), 9, 4, 1, 2)
- else
- SetPedComponentVariation(PlayerPedId(), 9, 6, 1, 2)
- end
- end
-
- SetPedArmour(PlayerPedId(), 100)
- PlaySoundFrontend(-1, "PICK_UP", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
-end
-
-function removeBulletproofVest()
- if(config.enableOutfits == true) then
- SetPedComponentVariation(PlayerPedId(), 9, 0, 1, 2)
- end
-
- SetPedArmour(PlayerPedId(), 0)
- PlaySoundFrontend(-1, "PICK_UP", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
-end
-
-function GiveCustomWeapon(weaponData)
- GiveWeaponToPed(PlayerPedId(), GetHashKey(weaponData), -1, false, true)
- SetCurrentPedWeapon(PlayerPedId(), GetHashKey("WEAPON_UNARMED"), true)
- PlaySoundFrontend(-1, "PICK_UP", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
-end
-
-function CloseArmory()
- if not IsAnySpeechPlaying(armoryPed) then
- PlayAmbientSpeechWithVoice(armoryPed, "WEPSEXPERT_BYESHOPGEN", "WEPSEXP", "SPEECH_PARAMS_FORCE", 0)
- end
-
- Wait(850)
- CloseMenu()
- RenderScriptCams(false, 1, 1000, 1, 0, 0)
- SetCamActive(ArmoryRoomCam, false)
- DestroyCam(ArmoryRoomCam, true)
-
- DoScreenFadeOut(500)
- Wait(600)
-
- if DoesEntityExist(armoryPed) then
- DeleteEntity(armoryPed)
- end
-
- FreezeEntityPosition(PlayerPedId(), false)
- SetEntityCoords(PlayerPedId(), Lx, Ly, Lz)
-
- Citizen.Wait(500)
- DoScreenFadeIn(500)
-end
-
-
-function openWeaponListMenu()
- CloseMenu()
- SendNUIMessage({
- title = i18n.translate("armory_global_title"),
- subtitle = i18n.translate("armory_weapons_list"),
- buttons = buttonWeaponList,
- action = "setAndOpen"
- })
-
- anyMenuOpen.menuName = "armory-weapon_list"
- anyMenuOpen.isActive = true
-end
-
-function OpenArmory()
- if((anyMenuOpen.menuName ~= "armory" and anyMenuOpen.menuName ~= "armory-weapon_list") and not anyMenuOpen.isActive) then
- SendNUIMessage({
- title = i18n.translate("armory_global_title"),
- subtitle = GetLabelText("PM_WEAPONS"),
- buttons = buttonsCategories,
- action = "setAndOpen"
- })
-
- anyMenuOpen.menuName = "armory"
- anyMenuOpen.isActive = true
- end
-end
-
-function BackArmory()
- CloseMenu()
- OpenArmory()
-end
\ No newline at end of file
diff --git a/resources/police/client/client.lua b/resources/police/client/client.lua
deleted file mode 100644
index 18cea6433..000000000
--- a/resources/police/client/client.lua
+++ /dev/null
@@ -1,890 +0,0 @@
---[[
- Cops_FiveM - A cops script for FiveM RP servers.
- Copyright (C) 2018 FiveM-Scripts
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero 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 Affero General Public License for more details.
-You should have received a copy of the GNU Affero General Public License
-along with Cops_FiveM in the file "LICENSE". If not, see .
-]]
-
---
---Local variables : Please do not touch theses variables
---
-
-if(config.useCopWhitelist == true) then
- isCop = false
-else
- isCop = true
-end
-
-local firstSpawn = true
-local isInService = false
-local policeHeli = nil
-local handCuffed = false
-local isAlreadyDead = false
-local allServiceCops = {}
-local blipsCops = {}
-local drag = false
-local officerDrag = -1
-
-rank = -1
-
-anyMenuOpen = {
- menuName = "",
- isActive = false
-}
-
-SpawnedSpikes = {}
-
---
---Events handlers
---
-
-AddEventHandler("playerSpawned", function()
- if config.useCopWhitelist then
- TriggerServerEvent("police:checkIsCop")
- else
- isCop = true
- TriggerServerEvent("police:checkIsCop")
- load_armory()
- load_garage()
- end
-
- if firstSpawn then
- TriggerServerEvent("police:GetPayChecks")
- firstSpawn = false
- end
-end)
-
-RegisterNetEvent('police:receiveIsCop')
-AddEventHandler('police:receiveIsCop', function(svrank, svdept)
- if(svrank == -1) then
- if(config.useCopWhitelist == true) then
- isCop = false
- else
- isCop = true
- rank = 0
- dept = 1
-
- load_armory()
- load_garage()
- end
- else
- isCop = true
- rank = svrank
- dept = svdept
- if(isInService) then --and config.enableOutfits
- if(GetEntityModel(PlayerPedId()) == GetHashKey("mp_m_freemode_01")) then
- SetPedComponentVariation(PlayerPedId(), 10, 8, config.rank.outfit_badge[rank], 2)
- else
- SetPedComponentVariation(PlayerPedId(), 10, 7, config.rank.outfit_badge[rank], 2)
- end
- end
-
- load_armory()
- load_garage()
- end
-end)
-
-if(config.useCopWhitelist == true) then
- RegisterNetEvent('police:nowCop')
- AddEventHandler('police:nowCop', function()
- isCop = true
- end)
-end
-
-RegisterNetEvent('police:Update')
-AddEventHandler('police:Update', function(boolState)
- local data = GetResourceMetadata(GetCurrentResourceName(), 'resource_fname', 0)
-
- if boolState then
- DisplayNotificationLabel("FMMC_ENDVERC1", "~y~" .. data .. "~s~")
- end
-end)
-
-if(config.useCopWhitelist == true) then
- RegisterNetEvent('police:noLongerCop')
- AddEventHandler('police:noLongerCop', function()
- if(config.useCopWhitelist == true) then
- isCop = false
- end
-
- isInService = false
-
- if(config.enableOutfits == true) then
- RemoveAllPedWeapons(PlayerPedId())
- TriggerServerEvent("skin_customization:SpawnPlayer")
- else
- local model = GetHashKey("a_m_y_mexthug_01")
-
- RequestModel(model)
- while not HasModelLoaded(model) do
- Citizen.Wait(0)
- end
-
- SetPlayerModel(PlayerId(), model)
- SetModelAsNoLongerNeeded(model)
- RemoveAllPedWeapons(PlayerPedId())
- end
-
- if(policeHeli ~= nil) then
- SetEntityAsMissionEntity(policeHeli, true, true)
- Citizen.InvokeNative(0xEA386986E786A54F, Citizen.PointerValueIntInitialized(policeHeli))
- policeHeli = nil
- end
-
- ServiceOff()
- end)
-end
-
-RegisterNetEvent('police:getArrested')
-AddEventHandler('police:getArrested', function()
- handCuffed = not handCuffed
- if(handCuffed) then
- TriggerEvent("police:notify", "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, i18n.translate("now_cuffed"))
- else
- TriggerEvent("police:notify", "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, i18n.translate("now_uncuffed"))
- cuffing = false
- drag = false
- ClearPedTasksImmediately(PlayerPedId())
- end
-end)
-
---Inspired from emergency for request system (by Jyben : https://forum.fivem.net/t/release-job-save-people-be-a-hero-paramedic-emergency-coma-ko/19773)
-local lockAskingFine = false
-RegisterNetEvent('police:payFines')
-AddEventHandler('police:payFines', function(amount, sender)
- Citizen.CreateThread(function()
-
- if(lockAskingFine ~= true) then
- lockAskingFine = true
- local notifReceivedAt = GetGameTimer()
- Notification(i18n.translate("info_fine_request_before_amount")..amount..i18n.translate("info_fine_request_after_amount"))
- while(true) do
- Wait(0)
-
- if (GetTimeDifference(GetGameTimer(), notifReceivedAt) > 15000) then
- TriggerServerEvent('police:finesETA', sender, 2)
- Notification(i18n.translate("request_fine_expired"))
- lockAskingFine = false
- break
- end
-
- if IsControlPressed(1, config.bindings.accept_fine) then
- TriggerServerEvent('bank:withdraw', amount)
- Notification(i18n.translate("pay_fine_success_before_amount")..amount..i18n.translate("pay_fine_success_after_amount"))
- TriggerServerEvent('police:finesETA', sender, 0)
- lockAskingFine = false
- break
- end
-
- if IsControlPressed(1, config.bindings.refuse_fine) then
- TriggerServerEvent('police:finesETA', sender, 3)
- lockAskingFine = false
- break
- end
- end
- else
- TriggerServerEvent('police:finesETA', sender, 1)
- end
- end)
-end)
-
-RegisterNetEvent('police:receivePaycheck')
-AddEventHandler('police:receivePaycheck', function(amount)
- if amount then
- local _, currentValue = StatGetInt("BANK_BALANCE", -1)
- local value = math.floor(amount + currentValue)
-
- StatSetInt("BANK_BALANCE", value, true)
- ShowHudComponentThisFrame(4)
- end
-end)
-
--- Copy/paste from fs_freemode (by FiveM-Script: https://github.com/FiveM-Scripts/fs_freemode)
-
-RegisterNetEvent("police:notify")
-AddEventHandler("police:notify", function(icon, type, sender, title, text)
- SetNotificationTextEntry("STRING")
- AddTextComponentString(text)
- SetNotificationMessage(icon, icon, true, type, sender, title, text)
- DrawNotification(false, true)
-end)
-
---Piece of code given by Thefoxeur54
-RegisterNetEvent('police:unseatme')
-AddEventHandler('police:unseatme', function(t)
- local ped = GetPlayerPed(t)
- ClearPedTasksImmediately(ped)
- plyPos = GetEntityCoords(PlayerPedId(), true)
- local xnew = plyPos.x+2
- local ynew = plyPos.y+2
-
- SetEntityCoords(PlayerPedId(), xnew, ynew, plyPos.z)
-end)
-
-RegisterNetEvent('police:toggleDrag')
-AddEventHandler('police:toggleDrag', function(t)
- if(handCuffed) then
- drag = not drag
- officerDrag = t
- end
-end)
-
-RegisterNetEvent('police:forcedEnteringVeh')
-AddEventHandler('police:forcedEnteringVeh', function(veh)
- if(handCuffed) then
- local pos = GetEntityCoords(PlayerPedId())
- local entityWorld = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0.0, 20.0, 0.0)
-
- local rayHandle = CastRayPointToPoint(pos.x, pos.y, pos.z, entityWorld.x, entityWorld.y, entityWorld.z, 10, PlayerPedId(), 0)
- local _, _, _, _, vehicleHandle = GetRaycastResult(rayHandle)
-
- if vehicleHandle ~= nil then
- if(IsVehicleSeatFree(vehicleHandle, 1)) then
- SetPedIntoVehicle(PlayerPedId(), vehicleHandle, 1)
- else
- if(IsVehicleSeatFree(vehicleHandle, 2)) then
- SetPedIntoVehicle(PlayerPedId(), vehicleHandle, 2)
- end
- end
- end
- end
-end)
-
-RegisterNetEvent('police:removeWeapons')
-AddEventHandler('police:removeWeapons', function()
- RemoveAllPedWeapons(PlayerPedId(), true)
-end)
-
-if(config.enableOtherCopsBlips == true) then
- RegisterNetEvent('police:resultAllCopsInService')
- AddEventHandler('police:resultAllCopsInService', function(array)
- allServiceCops = array
- enableCopBlips()
- end)
-end
-
---
---Functions
---
-
-function Notification(msg)
- SetNotificationTextEntry("STRING")
- AddTextComponentString(msg)
- DrawNotification(0,1)
-end
-
-function drawNotification(text)
- SetNotificationTextEntry("STRING")
- AddTextComponentString(text)
- DrawNotification(false, false)
-end
-
-function DisplayNotificationLabel(label, sublabel)
- SetNotificationTextEntry(label)
- if sublabel then
- AddTextComponentSubstringPlayerName(sublabel)
- end
-
- DrawNotification(true, true)
-end
-
---From Player Blips and Above Head Display (by Scammer : https://forum.fivem.net/t/release-scammers-script-collection-09-03-17/3313)
-function enableCopBlips()
- for k, existingBlip in pairs(blipsCops) do
- RemoveBlip(existingBlip)
- end
- blipsCops = {}
-
- local localIdCops = {}
- for _, player in ipairs(GetActivePlayers()) do
- if(GetPlayerPed(player) ~= PlayerPedId()) then
- for i,c in pairs(allServiceCops) do
- if(i == GetPlayerServerId(player)) then
- localIdCops[player] = c
- break
- end
- end
- end
- end
-
- for id, c in pairs(localIdCops) do
- local ped = GetPlayerPed(id)
- local blip = GetBlipFromEntity(ped)
-
- if not DoesBlipExist(blip) then
- blip = AddBlipForEntity(ped)
- SetBlipSprite(blip, 1)
- Citizen.InvokeNative( 0x5FBCA48327B914DF, blip, true)
- HideNumberOnBlip( blip)
- SetBlipNameToPlayerName(blip, id)
-
- SetBlipScale(blip, 0.85)
- SetBlipAlpha(blip, 255)
-
- table.insert(blipsCops, blip)
- else
- blipSprite = GetBlipSprite(blip)
-
- HideNumberOnBlip(blip)
- if blipSprite ~= 1 then
- SetBlipSprite(blip, 1)
- Citizen.InvokeNative(0x5FBCA48327B914DF, blip, true)
- end
-
- SetBlipNameToPlayerName(blip, id)
- SetBlipScale(blip, 0.85)
- SetBlipAlpha(blip, 255)
-
- table.insert(blipsCops, blip)
- end
- end
-end
-
-function GetPlayers()
- local players = {}
-
- for _, player in ipairs(GetActivePlayers()) do
- if NetworkIsPlayerActive(player) then
- table.insert(players, player)
- end
- end
-
- return players
-end
-
-function GetClosestPlayer()
- local players = GetPlayers()
- local closestDistance = -1
- local closestPlayer = -1
- local ply = PlayerPedId()
- local plyCoords = GetEntityCoords(ply, 0)
-
- for index,value in ipairs(players) do
- local target = GetPlayerPed(value)
- if(target ~= ply) then
- local targetCoords = GetEntityCoords(GetPlayerPed(value), 0)
- local distance = Vdist(targetCoords["x"], targetCoords["y"], targetCoords["z"], plyCoords["x"], plyCoords["y"], plyCoords["z"])
- if(closestDistance == -1 or closestDistance > distance) then
- closestPlayer = value
- closestDistance = distance
- end
- end
- end
-
- return closestPlayer, closestDistance
-end
-
-function drawTxt(text,font,centre,x,y,scale,r,g,b,a)
- SetTextFont(font)
- SetTextProportional(0)
- SetTextScale(scale, scale)
- SetTextColour(r, g, b, a)
- SetTextDropShadow(0, 0, 0, 0,255)
- SetTextEdge(1, 0, 0, 0, 255)
- SetTextDropShadow()
- SetTextOutline()
- SetTextCentre(centre)
- SetTextEntry("STRING")
- AddTextComponentString(text)
- DrawText(x, y)
-end
-
-function isNearTakeService()
- local distance = 10000
- local pos = {}
- for i = 1, #clockInStation do
- local coords = GetEntityCoords(PlayerPedId(), 0)
- local currentDistance = Vdist(clockInStation[i].x, clockInStation[i].y, clockInStation[i].z, coords.x, coords.y, coords.z)
- if(currentDistance < distance) then
- distance = currentDistance
- pos = clockInStation[i]
- end
- end
-
- if anyMenuOpen.menuName == "cloackroom" and anyMenuOpen.isActive and distance > 3 then
- CloseMenu()
- end
-
- if(distance < 30) then
- if anyMenuOpen.menuName ~= "cloackroom" and not anyMenuOpen.isActive then
- DrawMarker(1, pos.x, pos.y, pos.z-1, 0, 0, 0, 0, 0, 0, 1.0, 1.0, 1.0, 0, 155, 255, 200, 0, 0, 2, 0, 0, 0, 0)
- end
- end
-
- if(distance < 2) then
- return true
- end
-end
-
-function isNearStationGarage()
- local distance = 10000
- local pos = {}
- for i = 1, #garageStation do
- local coords = GetEntityCoords(PlayerPedId(), 0)
- local currentDistance = Vdist(garageStation[i].x, garageStation[i].y, garageStation[i].z, coords.x, coords.y, coords.z)
- if(currentDistance < distance) then
- distance = currentDistance
- pos = garageStation[i]
- end
- end
-
- if anyMenuOpen.menuName == "garage" and anyMenuOpen.isActive and distance > 5 then
- CloseMenu()
- end
-
- if(distance < 30) then
- if anyMenuOpen.menuName ~= "garage" and not anyMenuOpen.isActive then
- DrawMarker(1, pos.x, pos.y, pos.z-1, 0, 0, 0, 0, 0, 0, 2.0, 2.0, 1.0, 0, 155, 255, 200, 0, 0, 2, 0, 0, 0, 0)
- end
- end
-
- if(distance < 2) then
- return true
- end
-end
-
-function isNearHelicopterStation()
- local distance = 10000
- local pos = {}
- for i = 1, #heliStation do
- local coords = GetEntityCoords(PlayerPedId(), 0)
- local currentDistance = Vdist(heliStation[i].x, heliStation[i].y, heliStation[i].z, coords.x, coords.y, coords.z)
- if(currentDistance < distance) then
- distance = currentDistance
- pos = heliStation[i]
- end
- end
-
- if(distance < 30) then
- DrawMarker(1, pos.x, pos.y, pos.z-1, 0, 0, 0, 0, 0, 0, 2.5, 2.5, 1.0, 0, 155, 255, 200, 0, 0, 2, 0, 0, 0, 0)
- end
- if(distance < 2) then
- return true
- end
-end
-
-function isNearArmory()
- local distance = 10000
- local pos = {}
- for i = 1, #armoryStation do
- local coords = GetEntityCoords(PlayerPedId(), 0)
- local currentDistance = Vdist(armoryStation[i].x, armoryStation[i].y, armoryStation[i].z, coords.x, coords.y, coords.z)
- if(currentDistance < distance) then
- distance = currentDistance
- pos = armoryStation[i]
- end
- end
-
- if (anyMenuOpen.menuName == "armory" or anyMenuOpen.menuName == "armory-weapon_list") and anyMenuOpen.isActive and distance > 2 then
- CloseMenu()
- end
- if(distance < 30) then
- DrawMarker(1, pos.x, pos.y, pos.z-1, 0, 0, 0, 0, 0, 0, 1.0, 1.0, 1.0, 0, 155, 255, 200, 0, 0, 2, 0, 0, 0, 0)
- end
- if(distance < 2) then
- return true
- end
-end
-
-function ServiceOn()
- isInService = true
- TriggerServerEvent("police:takeService")
-end
-
-function ServiceOff()
- isInService = false
- TriggerServerEvent("police:breakService")
-
- if config.enableOtherCopsBlips == true then
- allServiceCops = {}
-
- for k, existingBlip in pairs(blipsCops) do
- RemoveBlip(existingBlip)
- end
- blipsCops = {}
- end
-end
-
-function DisplayHelpText(str)
- BeginTextCommandDisplayHelp("STRING")
- AddTextComponentSubstringPlayerName(str)
- EndTextCommandDisplayHelp(0, 0, 1, -1)
-end
-
-function CloseMenu()
- SendNUIMessage({
- action = "close"
- })
-
- anyMenuOpen.menuName = ""
- anyMenuOpen.isActive = false
-end
-
-RegisterNUICallback('sendAction', function(data, cb)
- _G[data.action](data.params)
- cb('ok')
-end)
-
---
---Threads
---
-
-local alreadyDead = false
-local playerStillDragged = false
-
-Citizen.CreateThread(function()
- DoScreenFadeIn(100)
- local gxt = "fmmc"
- local CurrentSlot = 0
-
- while HasAdditionalTextLoaded(CurrentSlot) and not HasThisAdditionalTextLoaded(gxt, CurrentSlot) do
- Wait(1)
- CurrentSlot = CurrentSlot + 1
- end
-
- if not HasThisAdditionalTextLoaded(gxt, CurrentSlot) then
- ClearAdditionalText(CurrentSlot, true)
- RequestAdditionalText(gxt, CurrentSlot)
- while not HasThisAdditionalTextLoaded(gxt, CurrentSlot) do
- Wait(0)
- end
- end
-
- RequestAnimDict('mp_arresting')
- while not HasAnimDictLoaded('mp_arresting') do
- Citizen.Wait(50)
- end
-
- if not IsIplActive("FIBlobby") then
- RequestIpl("FIBlobbyfake")
- end
-
- TriggerServerEvent("police:checkIsCop")
-
- if config.enableNeverWanted then
- SetMaxWantedLevel(0)
- SetWantedLevelMultiplier(0.0)
- else
- SetMaxWantedLevel(5)
- SetWantedLevelMultiplier(1.0)
- end
-
- if config.stationBlipsEnabled then
- for _, item in pairs(clockInStation) do
- item.blip = AddBlipForCoord(item.x, item.y, item.z)
- SetBlipSprite(item.blip, 60)
- SetBlipScale(item.blip, 1.0)
- SetBlipColour(item.blip, 38)
- SetBlipAsShortRange(item.blip, true)
- end
- end
-
- while true do
- Citizen.Wait(5)
- DisablePlayerVehicleRewards(PlayerId())
-
- if(anyMenuOpen.isActive) then
- DisableControlAction(1, 21)
- DisableControlAction(1, 140)
- DisableControlAction(1, 141)
- DisableControlAction(1, 142)
-
- SetDisableAmbientMeleeMove(PlayerPedId(), true)
-
- if (IsControlJustPressed(1,172)) then
- SendNUIMessage({
- action = "keyup"
- })
- PlaySoundFrontend(-1, "NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
- elseif (IsControlJustPressed(1,173)) then
- SendNUIMessage({
- action = "keydown"
- })
- PlaySoundFrontend(-1, "NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
- elseif (anyMenuOpen.menuName == "cloackroom") then
- if IsControlJustPressed(1, 176) then
- SendNUIMessage({
- action = "keyenter"
- })
-
- PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
- Citizen.Wait(500)
- CloseMenu()
- end
- elseif (IsControlJustPressed(1,176)) then
- SendNUIMessage({
- action = "keyenter"
- })
- PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
- elseif (IsControlJustPressed(1,177)) then
- if(anyMenuOpen.menuName == "policemenu" or anyMenuOpen.menuName == "cloackroom" or anyMenuOpen.menuName == "garage") then
- CloseMenu()
- elseif(anyMenuOpen.menuName == "armory") then
- CloseArmory()
- elseif(anyMenuOpen.menuName == "armory-weapon_list") then
- BackArmory()
- else
- BackMenuPolice()
- end
- end
- else
- EnableControlAction(1, 21)
- EnableControlAction(1, 140)
- EnableControlAction(1, 141)
- EnableControlAction(1, 142)
- end
-
- --Control death events
- if(config.useModifiedEmergency == false) then
- if(IsPlayerDead(PlayerId())) then
- if(alreadyDead == false) then
- if(isInService) then
- ServiceOff()
- end
-
- handCuffed = false
- drag = false
- alreadyDead = true
- end
- else
- alreadyDead = false
- end
- end
-
- if (handCuffed == true) then
- local myPed = PlayerPedId()
- local animation = 'idle'
- local flags = 50
-
- while IsPedBeingStunned(myPed, 0) do
- ClearPedTasksImmediately(myPed)
- end
-
- DisableControlAction(1, 12, true)
- DisableControlAction(1, 13, true)
- DisableControlAction(1, 14, true)
-
- DisableControlAction(1, 23, true)
- DisableControlAction(1, 24, true)
-
- DisableControlAction(1, 15, true)
- DisableControlAction(1, 16, true)
- DisableControlAction(1, 17, true)
-
- if not cuffing then
- SetCurrentPedWeapon(myPed, GetHashKey("WEAPON_UNARMED"), true)
- RemoveAllPedWeapons(myPed, true)
- cuffing = true
- end
-
- if not IsEntityPlayingAnim(myPed, "mp_arresting", animation, 3) then
- TaskPlayAnim(myPed, "mp_arresting", animation, 8.0, -8.0, -1, flags, 0, 0, 0, 0 )
- end
- else
- EnableControlAction(1, 12, false)
- EnableControlAction(1, 13, false)
- EnableControlAction(1, 14, false)
-
- EnableControlAction(1, 23, false)
- EnableControlAction(1, 24, false)
-
- EnableControlAction(1, 15, false)
- EnableControlAction(1, 16, false)
- EnableControlAction(1, 17, false)
-
- if IsEntityPlayingAnim(PlayerPedId(), "mp_arresting", "idle", 3) then
- StopAnimTask(PlayerPedId(), "mp_arresting", animation, 3)
- ClearPedTasksImmediately(PlayerPedId())
- end
-
- cuffing = false
- end
-
- --Piece of code from Drag command (by Frazzle, Valk, Michael_Sanelli, NYKILLA1127 : https://forum.fivem.net/t/release-drag-command/22174)
- if drag then
- local ped = GetPlayerPed(GetPlayerFromServerId(officerDrag))
- local myped = PlayerPedId()
- AttachEntityToEntity(myped, ped, 4103, 11816, 0.48, 0.00, 0.0, 0.0, 0.0, 0.0, false, false, false, false, 2, true)
- playerStillDragged = true
- else
- if(playerStillDragged) then
- DetachEntity(PlayerPedId(), true, false)
- playerStillDragged = false
- end
- end
-
- if config.enableNeverWanted then
- if IsPlayerWantedLevelGreater(PlayerId(), 0) then
- ClearPlayerWantedLevel(PlayerId())
- end
- end
-
- if(isCop) then
- if(isNearTakeService()) then
- if not (anyMenuOpen.isActive) then
- DisplayHelpText(i18n.translate("help_text_open_cloackroom") .. GetLabelText("collision_8vlv02g"),0,1,0.5,0.8,0.6,255,255,255,255)
- if IsControlJustPressed(1,config.bindings.interact_position) then
- load_cloackroom()
- OpenCloackroom()
- end
- end
- end
-
- if(isInService) then
- if(isNearStationGarage()) then
- if(policevehicle ~= nil) then
- if not (anyMenuOpen.isActive) then
- DisplayHelpText(i18n.translate("help_text_put_car_into_garage"),0,1,0.5,0.8,0.6,255,255,255,255)
- end
- else
- DisplayHelpText(i18n.translate("help_text_get_car_out_garage"),0,1,0.5,0.8,0.6,255,255,255,255)
- end
-
- if IsControlJustPressed(1,config.bindings.interact_position) then
- if(policevehicle ~= nil) then
- Citizen.InvokeNative(0xEA386986E786A54F, Citizen.PointerValueIntInitialized(policevehicle))
- policevehicle = nil
- else
- OpenGarage()
- end
- end
- end
-
- --Open Armory menu
- if(isNearArmory()) then
- if not (anyMenuOpen.isActive) then
- DisplayHelpText(i18n.translate("help_text_open_armory"),0,1,0.5,0.8,0.6,255,255,255,255)
-
- if IsControlJustPressed(1,config.bindings.interact_position) then
- Lx, Ly, Lz = table.unpack(GetEntityCoords(PlayerPedId(), true))
- DoScreenFadeOut(500)
- Wait(600)
-
- SetEntityCoords(PlayerPedId(), 452.119966796875, -980.061966796875, 30.690966796875)
- Wait(800)
- armoryPed = createArmoryPed()
-
- if not DoesCamExist(ArmoryRoomCam) then
- ArmoryRoomCam = CreateCam("DEFAULT_SCRIPTED_FLY_CAMERA", true)
- AttachCamToEntity(ArmoryRoomCam, PlayerPedId(), 0.0, 0.0, 1.0, true)
- PointCamAtEntity(ArmoryRoomCam, armoryPed, 0.0, -30.0, 1.0, true)
-
- SetCamRot(ArmoryRoomCam, 0.0,0.0, GetEntityHeading(PlayerPedId()))
- SetCamFov(ArmoryRoomCam, 70.0)
- end
-
- Wait(100)
- DoScreenFadeIn(500)
-
- if DoesEntityExist(armoryPed) then
- TaskTurnPedToFaceEntity(PlayerPedId(), armoryPed, -1)
- end
-
- Wait(300)
- OpenArmory()
- if not IsAmbientSpeechPlaying(armoryPed) then
- PlayAmbientSpeechWithVoice(armoryPed, "WEPSEXPERT_GREETSHOPGEN", "WEPSEXP", "SPEECH_PARAMS_FORCE", 0)
- end
- end
- end
- end
-
- if (anyMenuOpen.menuName == "armory") then
- if DoesCamExist(ArmoryRoomCam) then
- RenderScriptCams(true, 1, 1800, 1, 0)
- end
- end
-
- if (IsControlJustPressed(1,config.bindings.use_police_menu)) then
- load_menu()
- TogglePoliceMenu()
- end
-
- if isNearHelicopterStation() then
- if(policeHeli ~= nil) then
- DisplayHelpText(i18n.translate("help_text_put_heli_into_garage"),0,1,0.5,0.8,0.6,255,255,255,255)
- else
- DisplayHelpText(i18n.translate("help_text_get_heli_out_garage"),0,1,0.5,0.8,0.6,255,255,255,255)
- end
-
- if IsControlJustPressed(1,config.bindings.interact_position) then
- if(policeHeli ~= nil) then
- Citizen.InvokeNative(0xEA386986E786A54F, Citizen.PointerValueIntInitialized(policeHeli))
- policeHeli = nil
- else
- local heli = GetHashKey("polmav")
- local ply = PlayerPedId()
- local plyCoords = GetEntityCoords(ply, 0)
-
- RequestModel(heli)
- while not HasModelLoaded(heli) do
- Citizen.Wait(0)
- end
-
- policeHeli = CreateVehicle(heli, plyCoords["x"], plyCoords["y"], plyCoords["z"], 90.0, true, false)
- SetVehicleHasBeenOwnedByPlayer(policevehicle,true)
-
- local netid = NetworkGetNetworkIdFromEntity(policeHeli)
- SetNetworkIdCanMigrate(netid, true)
- NetworkRegisterEntityAsNetworked(VehToNet(policeHeli))
-
- SetVehicleLivery(policeHeli, 0)
- TaskWarpPedIntoVehicle(ply, policeHeli, -1)
- SetEntityAsMissionEntity(policeHeli, true, true)
- end
- end
- end
- end
- end
- end
-end)
-
-if config.enablePaychecks then
- Citizen.CreateThread(function()
- while true do
- Wait(1600)
- if GetClockHours() == 10 and GetClockMinutes() == 00 then
- TriggerServerEvent("police:TransferPayCheck")
- end
- end
- end)
-end
-
-Citizen.CreateThread(function()
- while true do
- if drag then
- local ped = GetPlayerPed(GetPlayerFromServerId(playerPedDragged))
- plyPos = GetEntityCoords(ped, true)
- SetEntityCoords(ped, plyPos.x, plyPos.y, plyPos.z)
- end
- Citizen.Wait(1000)
- end
-end)
-
-Citizen.CreateThread(function()
- while true do
- Citizen.Wait(1)
- if IsPedInAnyVehicle(PlayerPedId(), false) then
- currentVeh = GetVehiclePedIsIn(PlayerPedId(), false)
- x,y,z = table.unpack(GetEntityCoords(PlayerPedId(), true))
-
- if DoesObjectOfTypeExistAtCoords(x, y, z, 0.9, GetHashKey("P_ld_stinger_s"), true) then
- for i= 0, 7 do
- SetVehicleTyreBurst(currentVeh, i, true, 1148846080)
- end
-
- Citizen.Wait(100)
- DeleteSpike()
- end
- end
- end
-end)
diff --git a/resources/police/client/cloackroom.lua b/resources/police/client/cloackroom.lua
deleted file mode 100644
index da0e4cf92..000000000
--- a/resources/police/client/cloackroom.lua
+++ /dev/null
@@ -1,180 +0,0 @@
---[[
- Cops_FiveM - A cops script for FiveM RP servers.
- Copyright (C) 2018 FiveM-Scripts
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero 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 Affero General Public License for more details.
-You should have received a copy of the GNU Affero General Public License
-along with Cops_FiveM in the file "LICENSE". If not, see .
-]]
-
-local buttons = {}
-
-function load_cloackroom()
- for k in ipairs (buttons) do
- buttons [k] = nil
- end
-
- for k, data in pairs(skins) do
- if config.useCopWhitelist then
- if dept == k then
- for k, v in pairs(data) do
- buttons[#buttons+1] = {name = tostring(v.name), func = "clockIn", params = tostring(v.model)}
- end
- end
- else
- for k, v in pairs(data) do
- buttons[#buttons+1] = {name = tostring(v.name), func = "clockIn", params = tostring(v.model)}
- end
- end
- end
-
- buttons[#buttons+1] = {name = i18n.translate("cloackroom_break_service_title"), func = "clockOut", params = ""}
-
- if(config.enableOutfits == true) then
- if(rank <= 0) then
- buttons[#buttons+1] = {name = i18n.translate("cloackroom_add_yellow_vest_title"), func = "cloackroom_add_yellow_vest", params = ""}
- buttons[#buttons+1] = {name = i18n.translate("cloackroom_remove_yellow_vest_title"), func = "cloackroom_rem_yellow_vest", params = ""}
- end
- end
-end
-
-function clockIn(model)
- if model then
- if IsModelValid(model) and IsModelInCdimage(model) then
- ServiceOn()
- SetCopModel(model)
-
- drawNotification(i18n.translate("now_in_service_notification"))
- drawNotification(i18n.translate("help_open_menu_notification"))
- else
- drawNotification("This model is ~r~invalid~w~.")
- end
- end
-end
-
-function clockOut()
- ServiceOff()
- removeUniforme()
- drawNotification(i18n.translate("break_service_notification"))
-end
-
-function cloackroom_add_yellow_vest()
- Citizen.CreateThread(function()
- if(GetEntityModel(PlayerPedId()) == hashSkin) then
- SetPedComponentVariation(PlayerPedId(), 8, 59, 0, 2)
- else
- SetPedComponentVariation(PlayerPedId(), 8, 36, 0, 2)
- end
- end)
-end
-
-function cloackroom_rem_yellow_vest()
- Citizen.CreateThread(function()
- if(GetEntityModel(PlayerPedId()) == hashSkin) then
- SetPedComponentVariation(PlayerPedId(), 8, 58, 0, 2)
- else
- SetPedComponentVariation(PlayerPedId(), 8, 35, 0, 2)
- end
- end)
-end
-
-function SetCopModel(model)
- SetMaxWantedLevel(0)
- SetWantedLevelMultiplier(0.0)
- SetRelationshipBetweenGroups(0, GetHashKey("police"), GetHashKey("PLAYER"))
- SetRelationshipBetweenGroups(0, GetHashKey("PLAYER"), GetHashKey("police"))
-
- modelHash = GetHashKey(model)
-
- RequestModel(modelHash)
- while not HasModelLoaded(modelHash) do
- Citizen.Wait(0)
- end
-
- if model == "s_m_y_cop_01" then
- if (config.enableOutfits == true) then
- if(GetEntityModel(PlayerPedId()) == GetHashKey("mp_m_freemode_01")) then
- SetPedPropIndex(PlayerPedId(), 1, 5, 0, 2) --Sunglasses
- SetPedPropIndex(PlayerPedId(), 2, 0, 0, 2) --Bluetoothn earphone
- SetPedComponentVariation(PlayerPedId(), 11, 55, 0, 2) --Shirt
- SetPedComponentVariation(PlayerPedId(), 8, 58, 0, 2) --Nightstick decoration
- SetPedComponentVariation(PlayerPedId(), 4, 35, 0, 2) --Pants
- SetPedComponentVariation(PlayerPedId(), 6, 24, 0, 2) --Shooes
- SetPedComponentVariation(PlayerPedId(), 10, 8, config.rank.outfit_badge[rank], 2) --rank
- else
- SetPedPropIndex(PlayerPedId(), 1, 11, 3, 2) --Sunglasses
- SetPedPropIndex(PlayerPedId(), 2, 0, 0, 2) --Bluetoothn earphone
- SetPedComponentVariation(PlayerPedId(), 3, 14, 0, 2) --Non buggy tshirt
- SetPedComponentVariation(PlayerPedId(), 11, 48, 0, 2) --Shirt
- SetPedComponentVariation(PlayerPedId(), 8, 35, 0, 2) --Nightstick decoration
- SetPedComponentVariation(PlayerPedId(), 4, 34, 0, 2) --Pants
- SetPedComponentVariation(PlayerPedId(), 6, 29, 0, 2) --Shooes
- SetPedComponentVariation(PlayerPedId(), 10, 7, config.rank.outfit_badge[rank], 2) --rank
- end
- else
- SetPlayerModel(PlayerId(), modelHash)
- end
- elseif model == "s_m_y_hwaycop_01" then
- SetPlayerModel(PlayerId(), modelHash)
- SetPedComponentVariation(PlayerPedId(), 10, 7, config.rank.outfit_badge[rank], 2)
- elseif model == "s_m_y_sheriff_01" then
- SetPlayerModel(PlayerId(), modelHash)
- SetPedComponentVariation(PlayerPedId(), 10, 7, config.rank.outfit_badge[rank], 2)
- elseif model == "s_m_y_ranger_01" then
- SetPlayerModel(PlayerId(), modelHash)
- SetPedComponentVariation(PlayerPedId(), 10, 7, config.rank.outfit_badge[rank], 2)
- elseif model == "a_m_y_genstreet_01" then
-
- else
- SetPlayerModel(PlayerId(), modelHash)
- end
-
- giveBasicKit()
- SetModelAsNoLongerNeeded(modelHash)
-end
-
-function removeUniforme()
- if(config.enableOutfits == true) then
- RemoveAllPedWeapons(PlayerPedId())
- TriggerServerEvent("skin_customization:SpawnPlayer")
- else
- local model = GetHashKey("a_m_y_mexthug_01")
- RequestModel(model)
- while not HasModelLoaded(model) do
- Citizen.Wait(0)
- end
-
- SetPlayerModel(PlayerId(), model)
- SetModelAsNoLongerNeeded(model)
-
- SetMaxWantedLevel(5)
- SetWantedLevelMultiplier(1.0)
-
- SetRelationshipBetweenGroups(3, GetHashKey("police"), GetHashKey("PLAYER"))
- SetRelationshipBetweenGroups(3, GetHashKey("PLAYER"), GetHashKey("police"))
- end
-end
-
-function OpenCloackroom()
- if anyMenuOpen.menuName ~= "cloackroom" and not anyMenuOpen.isActive then
- SendNUIMessage({
- title = GetLabelText("collision_8vlv02g"),
- subtitle = GetLabelText("INPUT_CHARACTER_WHEEL"),
- buttons = buttons,
- action = "setAndOpen"
- })
-
- anyMenuOpen.menuName = "cloackroom"
- anyMenuOpen.isActive = true
- if config.enableVersionNotifier then
- TriggerServerEvent('police:UpdateNotifier')
- end
- end
-end
diff --git a/resources/police/client/garage.lua b/resources/police/client/garage.lua
deleted file mode 100644
index 536b3cae1..000000000
--- a/resources/police/client/garage.lua
+++ /dev/null
@@ -1,90 +0,0 @@
---[[
- Cops_FiveM - A cops script for FiveM RP servers.
- Copyright (C) 2018 FiveM-Scripts
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero 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 Affero General Public License for more details.
-You should have received a copy of the GNU Affero General Public License
-along with Cops_FiveM in the file "LICENSE". If not, see .
-]]
-
-local buttons = {}
-
-function load_garage()
- for k in ipairs (buttons) do
- buttons [k] = nil
- end
-
- for k, data in pairs(vehicles) do
- if config.useCopWhitelist then
- if dept == k then
- for k, v in pairs(data) do
- buttons[#buttons+1] = {name = tostring(v.name), func = "SpawnerVeh", params = tostring(v.model)}
- end
- end
- else
- if dept == 1 then
- for k, v in pairs(data) do
- buttons[#buttons+1] = {name = tostring(v.name), func = "SpawnerVeh", params = tostring(v.model)}
- end
- end
- end
- end
-end
-
-function SpawnerVeh(hash)
- if IsPedInAnyVehicle(PlayerPedId(), false) then
- currentVehicle = GetVehiclePedIsIn(PlayerPedId(), false)
- DeleteEntity(currentVehicle)
- end
-
- local car = GetHashKey(hash)
- local playerPed = PlayerPedId()
-
- RequestModel(car)
- while not HasModelLoaded(car) do
- Citizen.Wait(0)
- end
-
- local playerCoords = GetEntityCoords(playerPed)
- local playerHeading = GetEntityHeading(playerPed)
-
- policevehicle = CreateVehicle(car, playerCoords, 90.0, true, false)
- SetVehicleEngineOn(policevehicle, true, true, true)
- SetVehicleMod(policevehicle, 11, 2)
- SetVehicleMod(policevehicle, 12, 2)
- SetVehicleMod(policevehicle, 13, 2)
-
- SetEntityHeading(policevehicle, (playerHeading+160)%360)
- SetVehicleEnginePowerMultiplier(policevehicle, 25.0)
- SetVehicleOnGroundProperly(policevehicle)
- SetVehicleHasBeenOwnedByPlayer(policevehicle,true)
-
- SetVehRadioStation(policevehicle, "OFF")
-
- local netid = NetworkGetNetworkIdFromEntity(policevehicle)
- SetNetworkIdCanMigrate(netid, true)
- NetworkRegisterEntityAsNetworked(VehToNet(policevehicle))
-
- TaskWarpPedIntoVehicle(playerPed, policevehicle, -1)
- SetEntityInvincible(policevehicle, false)
-end
-
-function OpenGarage()
- CloseMenu()
- SendNUIMessage({
- title = i18n.translate("garage_global_title"),
- subtitle = GetLabelText("VEX_NMB"),
- buttons = buttons,
- action = "setAndOpen"
- })
-
- anyMenuOpen.menuName = "garage"
- anyMenuOpen.isActive = true
-end
\ No newline at end of file
diff --git a/resources/police/client/html/css/style.css b/resources/police/client/html/css/style.css
deleted file mode 100644
index d016a02dd..000000000
--- a/resources/police/client/html/css/style.css
+++ /dev/null
@@ -1,101 +0,0 @@
-/*!
- * Cops_FiveM Menu
- * Authors: Streetcorps, Kyominii
- * Website: Cops_FiveM
- * License: AGPL-3.0
- */
-
-@font-face {
- font-family: 'SignPainter';
- src: url('../fonts/SignPainter-HouseScript.ttf') format('truetype');
- font-weight: normal;
- font-style: normal;
-}
-
-html, body, {
- height: 100%;
-}
-
-body {
- font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
- padding-top: 5px;
-}
-
-.menu {
- float: right;
- margin-right: 10px;
- width: 418px;
- background: rgba(0, 0, 0, 0.8);
- display: none;
-}
-
-.header {
- background: rgb(30,87,153);
- background: url("../img/background.png") no-repeat;
- color: #fff;
- padding-top: 15px;
- font-size: 52px;
- font-family: 'SignPainter';
- min-height: 66px;
- text-align: center;
- text-shadow: 0 0 10px rgba(255, 255, 255, 0.3);
-}
-
-.subheader {
- height: 35px;
- color: #3e8fcc !important;
- background: rgb(0, 0, 0);
- box-shadow: 0px 5px 25px rgba(0, 0, 0, 0.5);
- font-size: 18px;
- padding-top: 10px;
- padding-left: 10px;
- overflow: hidden;
-}
-
-.content {
- background: linear-gradient(to bottom, rgba(0,0,0,0.2) 0%, rgba(0,0,0,0.8) 100%);
- box-shadow: 0px 5px 25px rgba(0, 0, 0, 0.5);
- user-select: none;
- color: #fff;
- font-size: 20px;
- overflow: hidden;
-}
-
-.list {
- padding-left: 0;
- margin-top: 0;
- margin-bottom: 0;
-}
-
-ul li:nth-of-type(1n+10) {
- display: none;
-}
-
-li {
- position: relative;
- padding: 10px;
- font-size: 17px;
- color: #D4D5D6;
- font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
- padding-top: 8px;
- padding-left: 10px;
- padding-bottom: 7px;
-}
-
-.item {
- list-style-type: none;
-}
-
-.item.active {
- color: #111;
- background: rgba(255,255,255,1);
- background: linear-gradient(to right, rgba(255,255,255,1) 0%, rgba(255,255,255,0.8) 100%);
-}
-
-.scroll {
- background: rgba(0, 0, 0, 0.7) url('../img/arrows_upanddown.jpg') center center no-repeat;
- border-top: 1px solid rgba(255, 255, 255, 0.2);
- display: none;
- height: 38px;
- width: 100%;
-}
\ No newline at end of file
diff --git a/resources/police/client/html/fonts/BebasNeue.otf b/resources/police/client/html/fonts/BebasNeue.otf
deleted file mode 100644
index 214e00754..000000000
Binary files a/resources/police/client/html/fonts/BebasNeue.otf and /dev/null differ
diff --git a/resources/police/client/html/fonts/SignPainter-HouseScript.ttf b/resources/police/client/html/fonts/SignPainter-HouseScript.ttf
deleted file mode 100644
index 099807c24..000000000
Binary files a/resources/police/client/html/fonts/SignPainter-HouseScript.ttf and /dev/null differ
diff --git a/resources/police/client/html/img/arrows_upanddown.jpg b/resources/police/client/html/img/arrows_upanddown.jpg
deleted file mode 100644
index 1efb10a18..000000000
Binary files a/resources/police/client/html/img/arrows_upanddown.jpg and /dev/null differ
diff --git a/resources/police/client/html/img/background.png b/resources/police/client/html/img/background.png
deleted file mode 100644
index b9b6cd84f..000000000
Binary files a/resources/police/client/html/img/background.png and /dev/null differ
diff --git a/resources/police/client/html/index.html b/resources/police/client/html/index.html
deleted file mode 100644
index 75e61fcc2..000000000
--- a/resources/police/client/html/index.html
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/resources/police/client/html/js/script.js b/resources/police/client/html/js/script.js
deleted file mode 100644
index 4a274b482..000000000
--- a/resources/police/client/html/js/script.js
+++ /dev/null
@@ -1,81 +0,0 @@
-$(document).ready(function(){
-
- window.addEventListener('message', (event) => {
- if(event.data.action == "setAndOpen"){
-
- $(".header").append(event.data.title);
- $(".subheader").append(event.data.subtitle);
-
- for(let i = 0; i < event.data.buttons.length; i++){
- let li = $("
").append(event.data.buttons[i].name).addClass("item").attr("function", event.data.buttons[i].func).attr("params", event.data.buttons[i].params);
- if(i == 0) {
- li.addClass("active");
- }
- $(".list").append(li);
- }
-
- var count = $("ul").children().length;
- if (count > 10) {
- $(".scroll").show();
- } else {
- $(".scroll").hide();
- }
-
- $(".menu").show();
- }
-
- if(event.data.action == "close"){
- $(".menu").hide();
- $(".list").empty();
- $(".header").empty();
- $(".subheader").empty();
- }
-
- if(event.data.action == "keyup"){
- if($(".item").length > 1) {
- let active = $(".active").removeClass("active");
-
- if(active.prev().length != 0 && active.prev().css("display") == "none"){
- $(".list").find(".item:visible:last").hide();
- active.prev().show();
- }
-
- if(active.prev().length == 0) {
- active.siblings().last().addClass("active");
- $(".item").hide();
- $(".item").slice(-10).show();
- } else {
- active.prev().addClass("active");
- }
- }
- }
-
- if(event.data.action == "keydown") {
- if($(".item").length > 1) {
- let active = $(".active").removeClass("active");
-
- if(active.next().length != 0 && active.next().css("display") == "none"){
- $(".list").find(".item:visible:first").hide();
- active.next().show();
- }
-
- if(active.next().length == 0) {
- active.siblings().first().addClass("active");
- $(".item").hide();
- $(".item").slice(0, 10).show();
- } else {
- active.next().addClass("active");
- }
- }
- }
-
- if(event.data.action == "keyenter"){
- let action = $(".active").attr("function");
- let params = $(".active").attr("params");
- $.post('http://police/sendAction', JSON.stringify({
- action: action,
- params: params
- }));
- }
- });
-});
\ No newline at end of file
diff --git a/resources/police/client/i18n.lua b/resources/police/client/i18n.lua
deleted file mode 100644
index fd6cec2f9..000000000
--- a/resources/police/client/i18n.lua
+++ /dev/null
@@ -1,42 +0,0 @@
-i18n = setmetatable({}, i18n)
-i18n.__index = i18n
-
-local store = {}
-local lang = {}
-avalLangs = {}
-
-function i18n.setup(l)
-
- if(l ~= nil)then
- lang = l
- end
-
-end
-
-function i18n.exportData()
- local result = store
- return result
-end
-
-function i18n.importData(l,s)
- table.insert( avalLangs, l)
- store[l] = s
-end
-
-function i18n.setLang(l)
- lang = l
-end
-
-function i18n.translate(key)
- local result = ""
- if(store == nil) then
- result = "Error 502 : no translation available !"
- else
- result = store[lang][key]
- if(result == nil) then
- result = "Error 404 : key not found !"
- end
- end
-
- return result
-end
\ No newline at end of file
diff --git a/resources/police/client/menu.lua b/resources/police/client/menu.lua
deleted file mode 100644
index dfc5781b2..000000000
--- a/resources/police/client/menu.lua
+++ /dev/null
@@ -1,484 +0,0 @@
---[[
- Cops_FiveM - A cops script for FiveM RP servers.
- Copyright (C) 2018 FiveM-Scripts
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero 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 Affero General Public License for more details.
-You should have received a copy of the GNU Affero General Public License
-along with Cops_FiveM in the file "LICENSE". If not, see .
-]]
-
-local buttonsCategories = {}
-local buttonsAnimation = {}
-local buttonsCitizen = {}
-local buttonsFine = {}
-local buttonsVehicle = {}
-local buttonsProps = {}
-
-function load_menu()
- for k in ipairs (buttonsCategories) do
- buttonsCategories [k] = nil
- end
-
- for k in ipairs (buttonsAnimation) do
- buttonsAnimation [k] = nil
- end
-
- for k in ipairs (buttonsCitizen) do
- buttonsCitizen [k] = nil
- end
-
- for k in ipairs (buttonsFine) do
- buttonsFine [k] = nil
- end
-
- for k in ipairs (buttonsVehicle) do
- buttonsVehicle [k] = nil
- end
-
- for k in ipairs (buttonsProps) do
- buttonsProps [k] = nil
- end
-
- --Categories
- buttonsCategories[#buttonsCategories+1] = {name = GetLabelText("CRW_ANIMATION"), func = "OpenAnimMenu", params = ""}
- buttonsCategories[#buttonsCategories+1] = {name = GetLabelText("collision_c29ovv"), func = "OpenCitizenMenu", params = ""}
- buttonsCategories[#buttonsCategories+1] = {name = GetLabelText("PIM_TVEHI"), func = "OpenVehMenu", params = ""}
- buttonsCategories[#buttonsCategories+1] = {name = GetLabelText("collision_9o6rwvf"), func = "OpenPropsMenu", params = ""}
-
- --Animations
- buttonsAnimation[#buttonsAnimation+1] = {name = i18n.translate("menu_anim_do_traffic_title"), func = 'DoTraffic', params = ""}
- buttonsAnimation[#buttonsAnimation+1] = {name = i18n.translate("menu_anim_take_notes_title"), func = 'Note', params = ""}
- buttonsAnimation[#buttonsAnimation+1] = {name = i18n.translate("menu_anim_standby_title"), func = 'StandBy', params = ""}
- buttonsAnimation[#buttonsAnimation+1] = {name = i18n.translate("menu_anim_standby_2_title"), func = 'StandBy2', params = ""}
- buttonsAnimation[#buttonsAnimation+1] = {name = i18n.translate("menu_anim_Cancel_emote_title"), func = 'CancelEmote', params = ""}
-
- --Citizens
- buttonsCitizen[#buttonsCitizen+1] = {name = i18n.translate("menu_weapons_title"), func = 'RemoveWeapons', params = ""}
- buttonsCitizen[#buttonsCitizen+1] = {name = i18n.translate("menu_toggle_cuff_title"), func = 'ToggleCuff', params = ""}
- buttonsCitizen[#buttonsCitizen+1] = {name = i18n.translate("menu_force_player_get_in_car_title"), func = 'PutInVehicle', params = ""}
- buttonsCitizen[#buttonsCitizen+1] = {name = i18n.translate("menu_force_player_get_out_car_title"), func = 'UnseatVehicle', params = ""}
- buttonsCitizen[#buttonsCitizen+1] = {name = i18n.translate("menu_drag_player_title"), func = 'DragPlayer', params = ""}
- buttonsCitizen[#buttonsCitizen+1] = {name = i18n.translate("menu_fines_title"), func = 'OpenMenuFine', params = ""}
-
- --Fines
- buttonsFine[#buttonsFine+1] = {name = "$250", func = 'Fines', params = 250}
- buttonsFine[#buttonsFine+1] = {name = "$500", func = 'Fines', params = 500}
- buttonsFine[#buttonsFine+1] = {name = "$1000", func = 'Fines', params = 1000}
- buttonsFine[#buttonsFine+1] = {name = "$1500", func = 'Fines', params = 1500}
- buttonsFine[#buttonsFine+1] = {name = "$2000", func = 'Fines', params = 2000}
- buttonsFine[#buttonsFine+1] = {name = "$4000", func = 'Fines', params = 4000}
- buttonsFine[#buttonsFine+1] = {name = "$6000", func = 'Fines', params = 6000}
- buttonsFine[#buttonsFine+1] = {name = "$8000", func = 'Fines', params = 8000}
- buttonsFine[#buttonsFine+1] = {name = "$10000", func = 'Fines', params = 10000}
- buttonsFine[#buttonsFine+1] = {name = i18n.translate("menu_custom_amount_fine_title"), func = 'Fines', params = -1}
-
- -- vehicles
- buttonsVehicle[#buttonsVehicle+1] = {name = i18n.translate("menu_crochet_veh_title"), func = 'Crochet', params = ""}
- buttonsVehicle[#buttonsVehicle+1] = {name = GetLabelText("FMMC_REMVEH"), func = 'DropVehicle', params = ""}
- buttonsVehicle[#buttonsVehicle+1] = {name = "Spike Stripes", func = 'SpawnSpikesStripe', params = ""}
-
- --Props
- for k,v in pairs(SpawnObjects) do
- buttonsProps[#buttonsProps+1] = {name = v.name, func = "SpawnProps", params = tostring(v.hash)}
- end
-
- buttonsProps[#buttonsProps+1] = {name=GetLabelText("FMMC_PR_23"), func = "SpawnProps", params="prop_mp_barrier_01b"}
- buttonsProps[#buttonsProps+1] = {name=GetLabelText("FMMC_PR_BARQADB"), func = "SpawnProps", params="prop_barrier_work05"}
- buttonsProps[#buttonsProps+1] = {name=GetLabelText("FMMC_DPR_LTRFCN"), func = "SpawnProps", params="prop_air_conelight"}
- buttonsProps[#buttonsProps+1] = {name=GetLabelText("FMMC_PR_PBARR"), func = "SpawnProps", params="prop_barrier_work06a"}
- buttonsProps[#buttonsProps+1] = {name=GetLabelText("FMMC_PR_CABTBTH"), func = "SpawnProps", params="prop_tollbooth_1"}
- buttonsProps[#buttonsProps+1] = {name=GetLabelText("FMMC_DPR_TRFCNE"), func = "SpawnProps", params="prop_mp_cone_01"}
- buttonsProps[#buttonsProps+1] = {name=GetLabelText("FMMC_DPR_TRFPLE"), func = "SpawnProps", params="prop_mp_cone_04"}
-
- buttonsProps[#buttonsProps+1] = {name = GetLabelText("collision_7x5xu9w"), func = "RemoveLastProps", params = ""}
- buttonsProps[#buttonsProps+1] = {name = GetLabelText("FMMC_REMOBJ"), func = "RemoveAllProps", params = ""}
-end
-
-function DoTraffic()
- Citizen.CreateThread(function()
- if not IsPedInAnyVehicle(PlayerPedId(), false) then
- TaskStartScenarioInPlace(PlayerPedId(), "WORLD_HUMAN_CAR_PARK_ATTENDANT", 0, false)
- Citizen.Wait(60000)
- ClearPedTasksImmediately(PlayerPedId())
- drawNotification(i18n.translate("menu_doing_traffic_notification"))
- else
- drawNotification(GetLabelText("PEN_EXITV"))
- end
- end)
-end
-
-function Note()
- Citizen.CreateThread(function()
- if not IsPedInAnyVehicle(PlayerPedId(), false) then
- TaskStartScenarioInPlace(PlayerPedId(), "WORLD_HUMAN_CLIPBOARD", 0, false)
- Citizen.Wait(20000)
- ClearPedTasksImmediately(PlayerPedId())
- else
- drawNotification(GetLabelText("PEN_EXITV"))
- end
- end)
-end
-
-function StandBy()
- Citizen.CreateThread(function()
- if not IsPedInAnyVehicle(PlayerPedId(), false) then
- TaskStartScenarioInPlace(PlayerPedId(), "WORLD_HUMAN_COP_IDLES", 0, true)
- Citizen.Wait(20000)
- ClearPedTasksImmediately(PlayerPedId())
- else
- drawNotification(GetLabelText("PEN_EXITV"))
- end
- end)
-end
-
-function StandBy2()
- Citizen.CreateThread(function()
- if not IsPedInAnyVehicle(PlayerPedId(), false) then
- TaskStartScenarioInPlace(PlayerPedId(), "WORLD_HUMAN_GUARD_STAND", 0, 1)
- Citizen.Wait(20000)
- ClearPedTasksImmediately(PlayerPedId())
- else
- drawNotification(GetLabelText("PEN_EXITV"))
- end
- end)
-end
-
-function CancelEmote()
- Citizen.CreateThread(function()
- ClearPedTasksImmediately(PlayerPedId())
- end)
-end
-
-function CheckInventory()
- local t, distance = GetClosestPlayer()
- if(distance ~= -1 and distance < 3) then
- TriggerServerEvent("police:targetCheckInventory", GetPlayerServerId(t))
- else
- drawNotification(i18n.translate("no_player_near_ped"))
- end
-end
-
-function RemoveWeapons()
- local t, distance = GetClosestPlayer()
- if(distance ~= -1 and distance < 3) then
- TriggerServerEvent("police:removeWeapons", GetPlayerServerId(t))
- else
- drawNotification(i18n.translate("no_player_near_ped"))
- end
-end
-
-function ToggleCuff()
- local t, distance = GetClosestPlayer()
- if(distance ~= -1 and distance < 3) then
- TriggerServerEvent("police:cuffGranted", GetPlayerServerId(t))
- else
- drawNotification(i18n.translate("no_player_near_ped"))
- end
-end
-
-function PutInVehicle()
- local t, distance = GetClosestPlayer()
- if(distance ~= -1 and distance < 3) then
- local v = GetVehiclePedIsIn(PlayerPedId(), true)
- TriggerServerEvent("police:forceEnterAsk", GetPlayerServerId(t), v)
- else
- drawNotification(i18n.translate("no_player_near_ped"))
- end
-end
-
-function UnseatVehicle()
- local t, distance = GetClosestPlayer()
- if(distance ~= -1 and distance < 3) then
- TriggerServerEvent("police:confirmUnseat", GetPlayerServerId(t))
- else
- drawNotification(i18n.translate("no_player_near_ped"))
- end
-end
-
-function DragPlayer()
- local t, distance = GetClosestPlayer()
- if(distance ~= -1 and distance < 3) then
- TriggerServerEvent("police:dragRequest", GetPlayerServerId(t))
- TriggerEvent("police:notify", "CHAR_ANDREAS", 1, i18n.translate("title_notification"), false, i18n.translate("drag_sender_notification_part_1") .. GetPlayerName(serverTargetPlayer) .. i18n.translate("drag_sender_notification_part_2"))
- else
- drawNotification(i18n.translate("no_player_near_ped"))
- end
-end
-
-function Fines(amount)
- local t, distance = GetClosestPlayer()
- if(distance ~= -1 and distance < 3) then
- Citizen.Trace("Price : "..tonumber(amount))
- if(tonumber(amount) == -1) then
- DisplayOnscreenKeyboard(1, "FMMC_KEY_TIP8S", "", "", "", "", "", 20)
- while (UpdateOnscreenKeyboard() == 0) do
- DisableAllControlActions(0);
- Wait(0);
- end
- if (GetOnscreenKeyboardResult()) then
- local res = tonumber(GetOnscreenKeyboardResult())
- if(res ~= nil and res ~= 0) then
- amount = tonumber(res)
- end
- end
-
- if(tonumber(amount) ~= -1) then
- TriggerServerEvent("police:finesGranted", GetPlayerServerId(t), tonumber(amount))
- end
- else
- TriggerServerEvent("police:finesGranted", GetPlayerServerId(t), tonumber(amount))
- end
- else
- drawNotification(i18n.translate("no_player_near_ped"))
- end
-end
-
-function Crochet()
- Citizen.CreateThread(function()
- local pos = GetEntityCoords(PlayerPedId())
- local entityWorld = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0.0, 20.0, 0.0)
-
- local rayHandle = CastRayPointToPoint(pos.x, pos.y, pos.z, entityWorld.x, entityWorld.y, entityWorld.z, 10, PlayerPedId(), 0)
- local _, _, _, _, vehicleHandle = GetRaycastResult(rayHandle)
- if DoesEntityExist(vehicleHandle) and IsEntityAVehicle(vehicleHandle) then
- local prevObj = GetClosestObjectOfType(pos.x, pos.y, pos.z, 10.0, GetHashKey("prop_weld_torch"), false, true, true)
- if(IsEntityAnObject(prevObj)) then
- SetEntityAsMissionEntity(prevObj)
- DeleteObject(prevObj)
- end
-
- TaskStartScenarioInPlace(PlayerPedId(), "WORLD_HUMAN_WELDING", 0, true)
- Citizen.Wait(20000)
- SetVehicleDoorsLocked(vehicleHandle, 1)
- ClearPedTasksImmediately(PlayerPedId())
- drawNotification(i18n.translate("menu_veh_opened_notification"))
- else
- drawNotification(i18n.translate("no_veh_near_ped"))
- end
- end)
-end
-
-function DropVehicle()
- Citizen.CreateThread(function()
- local pos = GetEntityCoords(PlayerPedId())
- local entityWorld = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0.0, 20.0, 0.0)
-
- local rayHandle = CastRayPointToPoint(pos.x, pos.y, pos.z, entityWorld.x, entityWorld.y, entityWorld.z, 10, PlayerPedId(), 0)
- local _, _, _, _, vehicleHandle = GetRaycastResult(rayHandle)
- if DoesEntityExist(vehicleHandle) and IsEntityAVehicle(vehicleHandle) then
- DeleteEntity(vehicleHandle)
- else
- drawNotification(i18n.translate("no_veh_near_ped"))
- end
- end)
-end
-
-function SpawnSpikesStripe()
- if IsPedInAnyPoliceVehicle(PlayerPedId()) then
- local modelHash = GetHashKey("P_ld_stinger_s")
- local currentVeh = GetVehiclePedIsIn(PlayerPedId(), false)
- local x,y,z = table.unpack(GetOffsetFromEntityInWorldCoords(currentVeh, 0.0, -5.2, -0.25))
-
- RequestScriptAudioBank("BIG_SCORE_HIJACK_01", true)
- Citizen.Wait(500)
-
- RequestModel(modelHash)
- while not HasModelLoaded(modelHash) do
- Citizen.Wait(0)
- end
-
- if HasModelLoaded(modelHash) then
- SpikeObject = CreateObject(modelHash, x, y, z, true, false, true)
- SetEntityNoCollisionEntity(SpikeObject, PlayerPedId(), 1)
- SetEntityDynamic(SpikeObject, false)
- ActivatePhysics(SpikeObject)
-
- if DoesEntityExist(SpikeObject) then
- local height = GetEntityHeightAboveGround(SpikeObject)
-
- SetEntityCoords(SpikeObject, x, y, z - height + 0.05)
- SetEntityHeading(SpikeObject, GetEntityHeading(PlayerPedId())-80.0)
- SetEntityCollision(SpikeObject, false, false)
- PlaceObjectOnGroundProperly(SpikeObject)
-
- SetEntityAsMissionEntity(SpikeObject, false, false)
- SetModelAsNoLongerNeeded(modelHash)
- PlaySoundFromEntity(-1, "DROP_STINGER", PlayerPedId(), "BIG_SCORE_3A_SOUNDS", 0, 0)
- end
- drawNotification("Spike stripe~g~ deployed~w~.")
- end
- else
- drawNotification("You need to get ~y~inside~w~ a ~y~police vehicle~w~.")
- PlaySoundFrontend(-1, "ERROR", "HUD_FRONTEND_DEFAULT_SOUNDSET", true)
- end
-end
-
-function DeleteSpike()
- local model = GetHashKey("P_ld_stinger_s")
- local x,y,z = table.unpack(GetEntityCoords(PlayerPedId(), true))
-
- if DoesObjectOfTypeExistAtCoords(x, y, z, 0.9, model, true) then
- local spike = GetClosestObjectOfType(x, y, z, 0.9, model, false, false, false)
- DeleteObject(spike)
- end
-end
-
-local propslist = {}
-
-function SpawnProps(model)
- if(#propslist < config.propsSpawnLimitByCop) then
- local prophash = GetHashKey(tostring(model))
- RequestModel(prophash)
- while not HasModelLoaded(prophash) do
- Citizen.Wait(0)
- end
-
- local offset = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0.0, 0.75, 0.0)
- local _, worldZ = GetGroundZFor_3dCoord(offset.x, offset.y, offset.z)
- local propsobj = CreateObjectNoOffset(prophash, offset.x, offset.y, worldZ, true, true, true)
- local heading = GetEntityHeading(PlayerPedId())
-
- SetEntityHeading(propsobj, heading)
- SetEntityAsMissionEntity(propsobj)
- SetModelAsNoLongerNeeded(prophash)
-
- propslist[#propslist+1] = ObjToNet(propsobj)
- end
-end
-
-function RemoveLastProps()
- DeleteObject(NetToObj(propslist[#propslist]))
- propslist[#propslist] = nil
-end
-
-function RemoveAllProps()
- for i, props in pairs(propslist) do
- DeleteObject(NetToObj(props))
- propslist[i] = nil
- end
-
-end
-
-function TogglePoliceMenu()
- if((anyMenuOpen.menuName ~= "policemenu" and anyMenuOpen.menuName ~= "policemenu-anim" and anyMenuOpen.menuName ~= "policemenu-citizens" and anyMenuOpen.menuName ~= "policemenu-veh" and anyMenuOpen.menuName ~= "policemenu-fines" and anyMenuOpen.menuName ~= "policemenu-props") and not anyMenuOpen.isActive) then
- SendNUIMessage({
- title = i18n.translate("menu_global_title"),
- subtitle = GetLabelText("PM_MP_OPTIONS"),
- buttons = buttonsCategories,
- action = "setAndOpen"
- })
-
- anyMenuOpen.menuName = "policemenu"
- anyMenuOpen.isActive = true
- else
- if((anyMenuOpen.menuName ~= "policemenu" and anyMenuOpen.menuName ~= "policemenu-anim" and anyMenuOpen.menuName ~= "policemenu-citizens" and anyMenuOpen.menuName ~= "policemenu-veh" and anyMenuOpen.menuName ~= "policemenu-fines" and anyMenuOpen.menuName ~= "policemenu-props") and anyMenuOpen.isActive) then
- CloseMenu()
- TogglePoliceMenu()
- else
- CloseMenu()
- end
- end
-end
-
-function BackMenuPolice()
- if(anyMenuOpen.menuName == "policemenu-anim" or anyMenuOpen.menuName == "policemenu-citizens" or anyMenuOpen.menuName == "policemenu-veh" or anyMenuOpen.menuName == "policemenu-props") then
- CloseMenu()
- TogglePoliceMenu()
- else
- CloseMenu()
- OpenCitizenMenu()
- end
-end
-
-function OpenAnimMenu()
- CloseMenu()
- SendNUIMessage({
- title = i18n.translate("menu_global_title"),
- subtitle = GetLabelText("CRW_ANIMATION"),
- buttons = buttonsAnimation,
- action = "setAndOpen"
- })
-
- anyMenuOpen.menuName = "policemenu-anim"
- anyMenuOpen.isActive = true
-end
-
-function OpenCitizenMenu()
- CloseMenu()
- SendNUIMessage({
- title = i18n.translate("menu_global_title"),
- subtitle = GetLabelText("collision_c29ovv"),
- buttons = buttonsCitizen,
- action = "setAndOpen"
- })
-
- anyMenuOpen.menuName = "policemenu-citizens"
- anyMenuOpen.isActive = true
-end
-
-function OpenVehMenu()
- CloseMenu()
- SendNUIMessage({
- title = i18n.translate("menu_global_title"),
- subtitle = GetLabelText("PIM_TVEHI"),
- buttons = buttonsVehicle,
- action = "setAndOpen"
- })
-
- anyMenuOpen.menuName = "policemenu-veh"
- anyMenuOpen.isActive = true
-end
-
-function OpenMenuFine()
- CloseMenu()
- SendNUIMessage({
- title = i18n.translate("menu_global_title"),
- subtitle = GetLabelText("PM_MP_OPTIONS"),
- buttons = buttonsFine,
- action = "setAndOpen"
- })
-
- anyMenuOpen.menuName = "policemenu-fines"
- anyMenuOpen.isActive = true
-end
-
-function OpenPropsMenu()
- CloseMenu()
- SendNUIMessage({
- title = i18n.translate("menu_global_title"),
- subtitle = GetLabelText("collision_9o6rwvf"),
- buttons = buttonsProps,
- action = "setAndOpen"
- })
-
- anyMenuOpen.menuName = "policemenu-props"
- anyMenuOpen.isActive = true
-end
-
-Citizen.CreateThread(function()
- while true do
- Citizen.Wait(5)
- for _, props in pairs(propslist) do
- local ox, oy, oz = table.unpack(GetEntityCoords(NetToObj(props), true))
- local cVeh = GetClosestVehicle(ox, oy, oz, 20.0, 0, 70)
- if(IsEntityAVehicle(cVeh)) then
- if IsEntityAtEntity(cVeh, NetToObj(props), 3.0, 5.0, 2.0, 0, 1, 0) then
- local cDriver = GetPedInVehicleSeat(cVeh, -1)
- TaskVehicleTempAction(cDriver, cVeh, 6, 1000)
-
- SetVehicleHandbrake(cVeh, true)
- SetVehicleIndicatorLights(cVeh, 0, true)
- SetVehicleIndicatorLights(cVeh, 1, true)
- end
- end
-
- end
- end
-end)
\ No newline at end of file
diff --git a/resources/police/config/cloackroom.lua b/resources/police/config/cloackroom.lua
deleted file mode 100644
index 99203d3fe..000000000
--- a/resources/police/config/cloackroom.lua
+++ /dev/null
@@ -1,32 +0,0 @@
-skins = {
- [0] = {
- {name="LSPD Officer", model="s_m_y_cop_01"},
- {name="SWAT Unit", model="BritishArmed"},
- {name="Biker Unit", model="s_m_y_hwaycop_01"},
- {name="High-Speed Unit", model="CSGOfbib"},
- {name="Prison Guard", model="s_m_m_prisguard_01"},
- {name="Undercover", model="s_m_y_cop_01"}
- },
- [1] = {
- {name="BCSO Sheriff", model="s_m_y_cop_01"},
- {name="SWAT Unit", model="BritishArmed"},
- {name="Biker Unit", model="s_m_y_hwaycop_01"},
- {name="High-Speed Unit", model="CSGOfbib"},
- {name="Prison Guard", model="s_m_m_prisguard_01"},
- {name="Undercover", model="s_m_y_cop_01"}
- },
- [2] = {
- {name="SASP Officer", model="s_m_y_cop_01"},
- {name="SWAT Unit", model="BritishArmed"},
- {name="Biker Unit", model="s_m_y_hwaycop_01"},
- {name="High-Speed Unit", model="CSGOfbib"},
- {name="Prison Guard", model="s_m_m_prisguard_01"},
- {name="Undercover", model="s_m_y_cop_01"}
- },
- [3] = {
- {name="Highway Patrol", model="s_m_y_hwaycop_01"}
- },
- [4] = {
- {name="Prison Officer", model="s_m_m_prisguard_01"}
- }
-}
\ No newline at end of file
diff --git a/resources/police/config/config.lua b/resources/police/config/config.lua
deleted file mode 100644
index 10141b287..000000000
--- a/resources/police/config/config.lua
+++ /dev/null
@@ -1,219 +0,0 @@
-config = {
- enableVersionNotifier = true, --notify if a new version is available (server console)
- enableOutfits = false,
-
- stationBlipsEnabled = true, -- switch between true or false to enable/disable blips for police stations
- useCopWhitelist = true,
-
- enableOtherCopsBlips = true,
- useNativePoliceGarage = false,
- enableNeverWanted = true,
-
- enablePaychecks = false,
- weekly_salary = 931,
-
- propsSpawnLimitByCop = 25,
-
- --Available languages : 'en', 'fr', 'de'
- lang = 'en',
-
- bindings = {
- interact_position = 51, -- E
- use_police_menu = 166, -- F5
- accept_fine = 246, -- Y
- refuse_fine = 45 -- R
- },
-
- --Customizable Departments
- departments = {
- label = {
- [0] = "Los Santos Police Department",
- [1] = "Blaine County Sheriff Office",
- [2] = "San Andreas State Police",
- [3] = "Federal Beauro of Investigation",
- [4] = "Prison Department"
- },
-
- minified_label = {
- [0] = "LSPD",
- [1] = "BCSO",
- [2] = "SASP",
- [3] = "FBI",
- [4] = "PRISON"
- }
- },
-
- --Customizable ranks
- rank = {
-
- --You can add or remove ranks as you want (just make sure to use numeric index, ascending)
- label = {
- [0] = "Trainee", -- Ranger Rank
- [1] = "Trainee", -- LSPD Rank
- [2] = "Trainee", -- Sheriff Rank
- [3] = "Trainee", -- State Highway Patrol Rank
-
- [4] = "Park Ranger",
- [5] = "Police Officer",
- [6] = "Deputy Sheriff",
- [7] = "State Trooper",
-
- [8] = "Park Ranger II",
- [9] = "Master Police Officer",
- [10] = "Deputy Sheriff II",
- [11] = "State Trooper II",
-
- [12] = "Sergeant",
- [13] = "Sergeant",
- [14] = "Sergeant",
- [15] = "Sergeant",
-
- [16] = "Lieutenant",
- [17] = "Lieutenant",
- [18] = "Lieutenant",
- [19] = "Lieutenant",
-
- [20] = "Captian",
- [21] = "Captian",
- [22] = "Captian",
- [23] = "Captian",
-
- [24] = "Game Warden ",
- [25] = "Chief of Police",
- [26] = "Sheriff",
- [27] = "Chief of SHP",
-
- [28] = "Ranger Admin Rank",
- [29] = "Police Admin Rank",
- [30] = "Sheriff Admin Rank",
- [31] = "SHP Admin Rank",
- },
-
- --Used for chat
- minified_label = {
- [0] = "TNE",
- [1] = "TNE", --1
- [2] = "TNE",
- [3] = "TNE",
-
- [4] = "PR",
- [5] = "PO", --2
- [6] = "DS",
- [7] = "ST",
-
- [8] = "PR2",
- [9] = "MPO", --3
- [10] = "DS2",
- [11] = "ST2",
-
- [12] = "SGT",
- [13] = "SGT", --4
- [14] = "SGT",
- [15] = "SGT",
-
- [16] = "LT",
- [17] = "LT", --5
- [18] = "LT",
- [19] = "LT",
-
- [20] = "CPT",
- [21] = "CPT", --6
- [22] = "CPT",
- [23] = "CPT",
-
- [24] = "GW",
- [25] = "COP", --7
- [26] = "SHF",
- [27] = "COS",
-
- [28] = "RAR",
- [29] = "APR", --8
- [30] = "ASR",
- [31] = "SSR",
- },
-
- --You can set here a badge for each rank you have. You have to enable "enableOutfits" to use this
- --The index is the rank index, the value is the badge index.
- --Here a link where you have the 4 MP Models badges with their index : https://kyominii.com/fivem/index.php/MP_Badges
- outfit_badge = {
- [0] = 0,
- [1] = 0,
- [2] = 0,
- [3] = 0,
-
- [4] = 0,
- [5] = 0,
- [6] = 0,
- [7] = 0,
-
- [8] = 1,
- [9] = 1,
- [10] = 1,
- [11] = 1,
-
- [12] = 1,
- [13] = 1,
- [14] = 1,
- [15] = 1,
-
- [16] = 2,
- [17] = 2,
- [18] = 2,
- [19] = 2,
-
- [20] = 2,
- [21] = 2,
- [22] = 2,
- [23] = 2,
-
- [24] = 3,
- [25] = 3,
- [26] = 3,
- [27] = 3,
-
- [28] = 3,
- [29] = 3,
- [30] = 3,
- [31] = 3,
- },
-
- --Minimum rank require to modify officers rank
- min_rank_set_rank = 24
- }
-}
-
-clockInStation = {
- {x=850.156677246094, y=-1283.92004394531, z=28.0047378540039}, -- La Mesa
- {x=457.956909179688, y=-992.72314453125, z=30.6895866394043}, -- Mission Row
- {x=1840.05, y=3690.34, z=34.29}, -- Sandy Shore
- {x=-439.6, y=5991.36, z=31.72}, -- Paleto Bay
- {x=-1093.0604248046875, y=-808.6140747070312, z=19.28019142150879}, -- Vespucci PD
- {x=360.3169860839844, y=-1583.9188232421875, z=29.291934967041016}, -- Davis Sheriff station
- {x=117.71, y=-761.21, z=45.75}, -- FIB Building
- {x=611.90, y=1.69, z=90.65}, -- Vinewood PD
- {x=1539.50, y=810.65, z=77.66} -- SAHP Highway PD
-}
-
-garageStation = {
- {x=-470.85266113281, y=6022.9296875, z=31.340530395508}, -- La Mesa
- {x=1873.3372802734, y=3687.3508300781, z=33.616954803467}, -- Mission Row
- {x=1870.68, y=3692.99, z=33.6}, -- Sandy Shores
- {x=855.24249267578, y=-1279.9300537109, z=26.513223648071 }, --Paleto Bay
- {x=-1070.1719970703125, y=-854.4666137695312, z=4.8671650886535645 }, -- Vespucci
- {x=383.7397766113281, y=-1624.2393798828125, z=29.291946411132812} -- Davis Sheriff station
-}
-
-heliStation = {
- {x=449.113966796875, y=-981.084966796875, z=43.691966796875} -- Mission Row
-}
-
-armoryStation = {
- {x=452.119966796875, y=-980.061966796875, z=30.690966796875}, -- La Mesa
- {x=853.157, y=-1267.74, z= 26.6729}, -- Mission Row
- {x=1851.62, y=3696.99, z=34.29}, -- Sandy Shore
- {x=-437.65, y= 5989.63, z=31.72}, -- Paleto Bay
- -- still need to add vespucci
- {x=352.9969177246094, y=-1592.7291259765625, z=29.291934967041016} -- Davis Sheriff station
-}
-
-i18n.setLang(tostring(config.lang))
diff --git a/resources/police/config/objects.lua b/resources/police/config/objects.lua
deleted file mode 100644
index 5ea5a5d4c..000000000
--- a/resources/police/config/objects.lua
+++ /dev/null
@@ -1,4 +0,0 @@
--- Configure the objects that cops can spawn on the map.
-SpawnObjects = {
- -- {name="Something", hash="prop_mp_barrier_01b"},
-}
\ No newline at end of file
diff --git a/resources/police/config/vehicles.lua b/resources/police/config/vehicles.lua
deleted file mode 100644
index d0265443c..000000000
--- a/resources/police/config/vehicles.lua
+++ /dev/null
@@ -1,28 +0,0 @@
-vehicles = {
- [0] = {
- {name="Park Ranger Truck", model="pranger"},
- },
- [1] = {
- {name="Police Buffalo", model="police2"},
- {name="Police Stanier", model="police"},
- {name="Police Interceptor", model="police3"},
- {name="Police Motorcycle", model="policeb"},
- {name="Police Transport Van", model="policet"},
- {name="Undercover Police Stanier", model="police4"}
- },
- [2] = {
- {name="Sheriff Stanier", model="sheriff"},
- {name="Sheriff Granger", model="sheriff2"},
- {name="Police Motorcycle", model="policeb"}
- },
- [3] = {
- {name="FIB Buffalo", model="fbi"},
- {name="FIB Granger", model="fbi2"},
- {name="Police Buffalo", model="police2"},
- },
- [4] = {
- {name="Police Stanier", model="police"},
- {name="Prison Transport Van", model="PBus"},
- {name="Sheriff Stanier", model="sheriff"},
- }
-}
\ No newline at end of file
diff --git a/resources/police/config/weapons.lua b/resources/police/config/weapons.lua
deleted file mode 100644
index 322187d85..000000000
--- a/resources/police/config/weapons.lua
+++ /dev/null
@@ -1,27 +0,0 @@
--- Configure the items that cops receive when they get on duty.
-basic_kit = {
- "WEAPON_PISTOL",
- "WEAPON_COMBATPISTOL",
- "WEAPON_STUNGUN",
- "WEAPON_NIGHTSTICK",
- "WEAPON_FLASHLIGHT",
- "WEAPON_CARBINERIFLE",
- "WEAPON_SPECIALCARBINE",
- "WEAPON_PUMPSHOTGUN",
- "WEAPON_SAWNOFFSHOTGUN",
- "WEAPON_FIREEXTINGUISHER",
- "WEAPON_FLARE"
-}
-
--- Configure the weapons that cops can choose in the armory room.
-weapons = {
- {name="Assault SMG", hash="WEAPON_ASSAULTSMG"},
- {name="Assault Shotgun", hash="WEAPON_ASSAULTSHOTGUN"},
- {name="Combact Pistol", hash="WEAPON_COMBATPISTOL"},
- {name="Heavy Sniper", hash="WEAPON_HEAVYSNIPER"},
- {name="Micro SMG", hash="WEAPON_MICROSMG"},
- {name="Pistol 50.", hash="WEAPON_PISTOL50"},
- {name="Shotgun", hash="WEAPON_PUMPSHOTGUN"},
- {name="SMG", hash="WEAPON_SMG"},
- {name="Smoke grenade", hash="WEAPON_SMOKEGRENADE"},
-}
\ No newline at end of file
diff --git a/resources/police/docs/features.md b/resources/police/docs/features.md
deleted file mode 100644
index db785ef63..000000000
--- a/resources/police/docs/features.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Current Features
-
-* support ghmattimysql
-* configurable (features and language)
-* cops whitelist
-* take/break service (positions with blips)
-* different service mode
-* cop garage (vehicle/heli)
-* fines (legacy feature)
-* cuff/uncuff
-* weapons removed (legacy feature)
-* force cuffed player to go in the vehicle
-* unseat this player (Thanks @Thefoxeur54 )
-* GUI menu with some animations
-* cops can see each other blips : (thanks @Scammer -- https://forum.fivem.net/t/release-scammers-script-collection-09-03-17/3313)
-* drag players (thanks @Frazzle and others : https://forum.fivem.net/t/release-drag-command/22174)
-* ranks (example of use : cloackroom.lua line 12)
-* so many other features ...
diff --git a/resources/police/docs/scripts.md b/resources/police/docs/scripts.md
deleted file mode 100644
index d764687e3..000000000
--- a/resources/police/docs/scripts.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Supported scripts
-* [ghmattimysql](https://github.com/GHMatti/ghmattimysql)
-* [Venomous Freemode](https://github.com/FiveM-Scripts/venomous-freemode)
diff --git a/resources/police/fxmanifest.lua b/resources/police/fxmanifest.lua
deleted file mode 100644
index 3a040af84..000000000
--- a/resources/police/fxmanifest.lua
+++ /dev/null
@@ -1,40 +0,0 @@
-fx_version 'bodacious'
-game 'gta5'
-version '1.5.1'
-
-ui_page('client/html/index.html')
-
-files({
- 'client/html/index.html',
- 'client/html/js/script.js',
- 'client/html/css/style.css',
- 'client/html/img/background.png',
- 'client/html/img/arrows_upanddown.jpg',
- 'client/html/fonts/SignPainter-HouseScript.ttf'
-})
-
-client_scripts {
- 'client/i18n.lua',
- 'locales/en.lua',
- 'locales/fr.lua',
- 'locales/de.lua',
- 'config/cloackroom.lua',
- 'config/config.lua',
- 'config/objects.lua',
- 'config/vehicles.lua',
- 'config/weapons.lua',
- 'client/client.lua',
- 'client/cloackroom.lua',
- 'client/menu.lua',
- 'client/garage.lua',
- 'client/armory.lua'
- }
-
-server_scripts {
- 'client/i18n.lua',
- 'locales/en.lua',
- 'locales/fr.lua',
- 'locales/de.lua',
- 'config/config.lua',
- 'server/server.lua'
-}
diff --git a/resources/police/locales/de.lua b/resources/police/locales/de.lua
deleted file mode 100644
index 0bdada070..000000000
--- a/resources/police/locales/de.lua
+++ /dev/null
@@ -1,139 +0,0 @@
-i18n.importData("de", {
- police_station = "Polizeistation",
- title_notification = "Regierung",
- now_cuffed = "Dir wurden die Handschellen angelegt !",
- now_uncuffed = "Freiheit !",
- info_fine_request_before_amount = "Drücke ~g~Y~s~ um das Strafgeld zu akzeptieren $",
- info_fine_request_after_amount = " , drücke ~r~R~s~ um es zu verweigern !",
- request_fine_expired = "Die Strafgeld Anfrage ist ~r~abgelaufen~s~ !",
- pay_fine_success_before_amount = "Du hast gerade $",
- pay_fine_success_after_amount = " Strafgeld gezahlt.",
- help_text_open_cloackroom = "Drücke ~INPUT_CONTEXT~ um die ~b~Polizei Garderobe zu öffnen",
- help_text_put_car_into_garage = "Drücke ~INPUT_CONTEXT~ um das Polizei Auto in die ~b~Garage zu parken",
- help_text_get_car_out_garage = "Drücke ~INPUT_CONTEXT~ um das Polizei Auto aus der ~b~Garage zu nehmen",
- help_text_put_heli_into_garage = "Drücke ~INPUT_CONTEXT~ um den Hubschrauber in die ~b~Garage zu parken",
- help_text_get_heli_out_garage = "Drücke ~INPUT_CONTEXT~ um den Hubschrauber aus der ~b~Garage zu nehmen",
- no_player_near_ped = "Kein Spieler in der Nähe",
- no_veh_near_ped = "Kein Fahrzeug in der Nähe",
- cop_whitelist_disabled = "Cop whitelist is disable, please enable the whitelist to use this command !",
-
- menu_id_card_title = "ID Karte",
- menu_check_inventory_title = "Kontrolliere das Inventar",
- menu_toggle_cuff_title = "Handschellen anglegen/abnehmen",
- menu_weapons_title = "Waffe beschlagnahmen",
- menu_force_player_get_in_car_title = "Ins Fahrzeug befördern",
- menu_force_player_get_out_car_title = "Aus dem Fahrzeug ziehen",
- menu_drag_player_title = "Den Spieler tragen",
- menu_fines_title = "Strafgeld",
- menu_check_plate_title = "Kennzeichen kontrollieren",
- menu_crochet_veh_title = "Fahrzeug aufbrechen",
- menu_global_title = "Polizei Menu",
- menu_categories_title = "Kategorien",
- menu_animations_title = "Animationen",
- menu_citizens_title = "Bürger",
- menu_vehicles_title = "Fahrzeuge",
- menu_close_menu_title = "Schließe das Menu",
- menu_anim_do_traffic_title = "Mach einen auf Traffik Polizisten",
- menu_anim_take_notes_title = "Nimm Notizen",
- menu_anim_standby_title = "Bereit stehen",
- menu_anim_standby_2_title = "Bereit stehen 2",
- menu_anim_Cancel_emote_title = "Abbrechen emote",
-
- menu_custom_amount_fine_title = "Benutzerdefinierte anzahl",
- menu_doing_traffic_notification = "~g~Du machst einen auf Traffik Polizisten.",
- menu_taking_notes_notification = "~g~Du bist am Notizen schreiben.",
- menu_being_stand_by_notification = "~g~Du stehst bereit.",
- menu_veh_opened_notification = "Das Fahrzeug ist jetzt ~g~offen~w~.",
-
- menu_put_in_jail_title = "Ins Gefängis bringen",
- menu_arrest_title = "Verhaften",
- menu_custom_amount_jail_title = "Benutzerdefinierte anzahl an Sekunden",
- jail_notification_title = "^4[JAIL]",
- jail_arrest_notification_part_1 = "Du wurdest verhaftet für ^1", -- send to the client after he got puted into the jail
- jail_arrest_notification_part_2 = " ^0Sekunden!",
- jail_weapons_removed = "Deine Waffen wurden entfernt weil du verhaftet wurdest!",
- jail_not_cuffed = "Der Spieler muss an Handschellen gefässelt sein!",
- jail_remove_weapons_notification_part_1 = "Alle Waffen vom ",
- jail_remove_weapons_notification_part_2 = " wurden entfernt.",
- menu_delete_vehicle_title = "Fahrzeug Löschen",
-
- garage_global_title = "Polizei Garage",
- garage_loading = "~b~Laden...",
-
- cloackroom_global_title = "Polizei Garderobe",
- cloackroom_take_service_ranger_title = "Clock in as Park Ranger",
- cloackroom_take_service_sheriff_title = "Clock in as Sheriff",
- cloackroom_take_service_chp_title = "Clock in as State Trooper",
- cloackroom_take_service_prison_title = "Clock in as a Prison Guard",
- cloackroom_take_service_normal_title = "Dienst beginnen (Uniformed Officer)",
- cloackroom_take_service_hidden_title = "Dienst beginnen (Undercover)",
- cloackroom_take_service_swat_title = "Dienst beginnen (SWAT)",
- cloackroom_break_service_title = "Dienst abbrechen",
- cloackroom_add_bulletproof_vest_title = "Schußsichere Weste anlegen",
- cloackroom_remove_bulletproof_vest_title = "Schußsichere Weste entfernen",
- cloackroom_add_yellow_vest_title = "Gelbe Warnweste anlegen",
- cloackroom_remove_yellow_vest_title = "Gelbe Warnweste entfernen",
- now_in_service_notification = "Du bist nun im ~g~Dienst",
- break_service_notification = "Du hast deinen ~r~Dienst abgebrochen",
- help_open_menu_notification = "Drücke ~g~F5~w~ um das ~b~Polizei Menu ~w~zu öffnen",
-
- menu_props_title = "Objects",
- menu_spawn_props_title = "Laichen ein props",
- menu_spawn_barrier_title = "Spawn a police barrier",
- menu_spawn_work_ahead_barrier_title = "Spawn work ahead barrier",
- menu_remove_last_props_title = "Entfernen letzte props",
- menu_remove_all_props_title = "Entfernen alle props",
- removed_prop = "Object has been ~g~removed~w~.",
- removed_props = "Objects have been ~g~removed~w~.",
-
- vehicle_checking_plate_part_1 = "Das Fahrzeug #", -- before number plate
- vehicle_checking_plate_part_2 = " gehört ", -- between number plate and player name when veh registered
- vehicle_checking_plate_part_3 = "", -- after player name when veh registered
- vehicle_checking_plate_not_registered = " ist nicht Registriert !", -- after player name
- unseat_sender_notification_part_1 = "", -- before player name
- unseat_sender_notification_part_2 = " ist Raus !", -- after player name
- drag_sender_notification_part_1 = "Tragen ", -- before player name
- drag_sender_notification_part_2 = "", -- after player name
- checking_inventory_part_1 = "",
- checking_inventory_part_2 = " sein Inventar : ",
- checking_weapons_part_1 = "",
- checking_weapons_part_2 = " seine Waffen : ",
- send_fine_request_part_1 = "Strafgeld Anfrage von $",
- send_fine_request_part_2 = " wurde an folgenden Spieler gesendet ",
- already_have_a_pendind_fine_request = " hat bereits eine Strafgeld Anfrage ausstehend",
- request_fine_timeout = " hat nicht auf die Strafgeld Anfrage reagiert",
- request_fine_refused = " hat die Strafgeld Anfrage verweigert",
- request_fine_accepted = " hat das Strafgeld bezahlt",
- toggle_cuff_player_part_1 = "Versuche Handschellen anzulegen am Spieler ",
- toggle_cuff_player_part_2 = "",
- force_player_get_in_vehicle_part_1 = "Versuche ",
- force_player_get_in_vehicle_part_2 = " in das Fahrzeug zu befördern",
- usage_command_copadd = "Benutze : /copadd [ID]",
- usage_command_coprem = "Benutze : /coprem [ID]",
- usage_command_coprank = "Benutze : /coprank [ID] [RANK]",
- command_received = "Roger that !",
- become_cop_success = "Herzlichen Glückwunsch, Sie sind nun ein Polizist !~w~",
- remove_from_cops = "Sie sind kein Polizist mehr !~w~.",
- no_player_with_this_id = "Kein Spieler mit folgender ID gefunden !",
- not_enough_permission = "Du hast nicht die benötigten Rechte um diesen Befehl auszuführen !",
- new_dept = "Congrats, you are now part of the",
- same_dept = "That's the same department!",
- new_rank = "Congrats, you are now : ",
- player_not_cop = "This player isn't a cop",
- rank_not_exist = "This rank doesn't exist",
- dept_not_exist = "This department doesn't exist",
-
- armory_global_title = "Polizei Waffenkammer",
- help_text_open_armory = "Drücke ~INPUT_CONTEXT~ um die Polizei Waffenkammer zu öffnen",
- armory_add_bulletproof_vest_title = "Schußsichere Weste anlegen",
- armory_remove_bulletproof_vest_title = "Schußsichere Weste entfernen",
- armory_weapons_list = "Waffen auswählen",
- armory_basic_kit = "Standart Polizei Kit",
-
- WEAPON_COMBATPISTOL = "Combat Pistol",
- WEAPON_PISTOL50 = "Pistol 50.",
- WEAPON_PUMPSHOTGUN = "Shotgun",
- WEAPON_ASSAULTSHOTGUN = "Assault Shotgun",
- WEAPON_ASSAULTSMG = "Assault SMG",
- WEAPON_HEAVYSNIPER = "Heavy Sniper"
-})
\ No newline at end of file
diff --git a/resources/police/locales/en.lua b/resources/police/locales/en.lua
deleted file mode 100644
index 47464cbdc..000000000
--- a/resources/police/locales/en.lua
+++ /dev/null
@@ -1,122 +0,0 @@
-i18n.importData("en", {
- police_station = "Police Station",
- title_notification = "Government",
- now_cuffed = "You've been hand cuffed!",
- now_uncuffed = "Freedom!",
- info_fine_request_before_amount = "Press ~g~Y~s~ to accept the $",
- info_fine_request_after_amount = " fine, press ~r~R~s~ to refuse !",
- request_fine_expired = "The fine request has just ~r~expired~s~ !",
- pay_fine_success_before_amount = "You have just paid a fine or summons of $",
- pay_fine_success_after_amount = " fine.",
- help_text_open_cloackroom = "Press ~INPUT_CONTEXT~ to open the ~b~",
- help_text_put_car_into_garage = "Press ~INPUT_CONTEXT~ to put the police vehicle into the ~b~garage",
- help_text_get_car_out_garage = "Press ~INPUT_CONTEXT~ to get a police vehicle out of the ~b~garage",
- help_text_put_heli_into_garage = "Press ~INPUT_CONTEXT~ to put the helicopter into the ~b~garage",
- help_text_get_heli_out_garage = "Press ~INPUT_CONTEXT~ to get an helicopter out of the ~b~garage",
- no_player_near_ped = "No players near you",
- no_veh_near_ped = "No vehicles near you",
- cop_whitelist_disabled = "Cop whitelist is disable, please enable the whitelist to use this command !",
- menu_id_card_title = "ID Card",
- menu_check_inventory_title = "Check Inventory",
- menu_toggle_cuff_title = "Toggle Hand-Cuffs",
- menu_weapons_title = "Confiscate weapons",
- menu_force_player_get_in_car_title = "Put player in vehicle!",
- menu_force_player_get_out_car_title = "Get player out of vehicle!",
- menu_drag_player_title = "Drag the player forcefully",
- menu_fines_title = "Fines and Summons",
- menu_check_plate_title = "Run Plates",
- menu_crochet_veh_title = "Lockpick car",
- menu_global_title = "Police Menu",
- menu_categories_title = "Categories",
- menu_animations_title = "Animations",
- menu_citizens_title = "Citizens",
- menu_vehicles_title = "Vehicles",
- menu_close_menu_title = "Close the menu",
- menu_anim_do_traffic_title = "Do a traffic stop",
- menu_anim_take_notes_title = "Take notes",
- menu_anim_standby_title = "Stand By",
- menu_anim_standby_2_title = "Stand By 2",
- menu_anim_Cancel_emote_title = "Cancel emote",
- menu_custom_amount_fine_title = "Custom amount",
- menu_doing_traffic_notification = "~g~You're now running a traffic stop.",
- menu_taking_notes_notification = "~g~You're taking notes.",
- menu_being_stand_by_notification = "~g~You're awaiting orders.",
- menu_veh_opened_notification = "The vehicle is ~g~open~w~.",
- menu_put_in_jail_title = "Put in jail",
- menu_arrest_title = "Arrest",
- menu_custom_amount_jail_title = "Custom amount in seconds",
- menu_delete_vehicle_title = "Delete Vehicle",
- jail_notification_title = "^4[JAIL]",
- jail_arrest_notification_part_1 = "You got Arrested for ^1", -- send to the client after he got put into the jail
- jail_arrest_notification_part_2 = " ^0seconds!",
- jail_weapons_removed = "Your Weapons have been removed for being Arrested!",
- jail_not_cuffed = "Player need to be cuffed!",
- jail_remove_weapons_notification_part_1 = "All the weapons from ",
- jail_remove_weapons_notification_part_2 = " got removed.",
- garage_global_title = "Police garage",
- garage_loading = "~b~Loading...",
- cloackroom_global_title = "Police's Cloackroom",
- cloackroom_take_service_ranger_title = "Clock in as Park Ranger",
- cloackroom_take_service_normal_title = "Clock in as Officer",
- cloackroom_take_service_sheriff_title = "Clock in as Sheriff",
- cloackroom_take_service_chp_title = "Clock in as State Trooper",
- cloackroom_take_service_prison_title = "Clock in as a Prison Guard",
- cloackroom_take_service_hidden_title = "Clock in as Detective",
- cloackroom_take_service_swat_title = "Clock in as S.W.A.T",
- cloackroom_break_service_title = "Clock out",
- cloackroom_add_yellow_vest_title = "Put on a yellow vest",
- cloackroom_remove_yellow_vest_title = "Remove your yellow vest",
- now_in_service_notification = "You've just ~g~clocked in",
- break_service_notification = "You've just ~r~clocked out",
- help_open_menu_notification = "Press ~g~F5~w~ to open ~b~the police menu",
- menu_props_title = "Objects",
- menu_spawn_props_title = "Spawn a cone",
- menu_spawn_barrier_title = "Spawn a police barrier",
- menu_spawn_work_ahead_barrier_title = "Spawn work ahead barrier",
- menu_remove_last_props_title = "Remove last props",
- menu_remove_all_props_title = "Remove all props",
- removed_prop = "Object has been ~g~removed~w~.",
- removed_props = "Objects have been ~g~removed~w~.",
- vehicle_checking_plate_part_1 = "The vehicle #", -- before number plate
- vehicle_checking_plate_part_2 = " belongs to ", -- between number plate and player name when veh registered
- vehicle_checking_plate_part_3 = "", -- after player name when veh registered
- vehicle_checking_plate_not_registered = " isn't registered!", -- after player name
- unseat_sender_notification_part_1 = "", -- before player name
- unseat_sender_notification_part_2 = " has escaped!", -- after player name
- drag_sender_notification_part_1 = "Dragging ", -- before player name
- drag_sender_notification_part_2 = "", -- after player name
- checking_inventory_part_1 = "",
- checking_inventory_part_2 = "'s inventory : ",
- checking_weapons_part_1 = "",
- checking_weapons_part_2 = "'s weapons : ",
- send_fine_request_part_1 = "Tell the player to pay a $",
- send_fine_request_part_2 = " fine request to ",
- already_have_a_pendind_fine_request = " already has a pending fine request",
- request_fine_timeout = " hasn't answered to the fine request",
- request_fine_refused = " has refused to pay thier fine",
- request_fine_accepted = " has paid the fine",
- toggle_cuff_player_part_1 = "Trying to toggle cuff to ",
- toggle_cuff_player_part_2 = "",
- force_player_get_in_vehicle_part_1 = "Trying to force ",
- force_player_get_in_vehicle_part_2 = " to enter the vehicle",
- usage_command_copadd = "Usage: /copadd [ID]",
- usage_command_coprem = "Usage: /coprem [ID]",
- usage_command_coprank = "Usage: /coprank [ID] [RANK]",
- command_received = "Roger that !",
- become_cop_success = "Welcome to the Force!~w~",
- remove_from_cops = "You've been fired !~w~.",
- no_player_with_this_id = "No player with this ID!",
- not_enough_permission = "You don't have the permission to execute this task.",
- new_dept = "Congrats, you are now part of the",
- same_dept = "That's the same department!",
- new_rank = "Congrats, you are now: ",
- player_not_cop = "This player isn't a cop",
- rank_not_exist = "This rank doesn't exist",
- dept_not_exist = "This department doesn't exist",
- armory_global_title = "Police Armory",
- help_text_open_armory = "Press ~INPUT_CONTEXT~ to open police's armory",
- armory_add_bulletproof_vest_title = "Put on a bulletproof vest",
- armory_remove_bulletproof_vest_title = "Take off your bulletproof vest",
- armory_weapons_list = "Choose weapons",
- armory_basic_kit = "Basic cop kit",
-})
\ No newline at end of file
diff --git a/resources/police/locales/fr.lua b/resources/police/locales/fr.lua
deleted file mode 100644
index a0a576c83..000000000
--- a/resources/police/locales/fr.lua
+++ /dev/null
@@ -1,130 +0,0 @@
-i18n.importData("fr", {
- police_station = "Station de police",
- title_notification = "Gouvernement",
- now_cuffed = "Vous êtes menotté !",
- now_uncuffed = "Liberté !",
- info_fine_request_before_amount = "Appuyez sur ~g~Y~s~ pour accepter l'amende de $",
- info_fine_request_after_amount = ", appuyez sur ~r~R~s~ pour la refuser !",
- request_fine_expired = "La demande de l'amende à ~r~expirée~s~ !",
- pay_fine_success_before_amount = "Vous avez payé l'amende de $",
- pay_fine_success_after_amount = ".",
- help_text_open_cloackroom = "Appuyez sur ~INPUT_CONTEXT~ pour ouvrir le ~b~vestiaire de Police",
- help_text_put_car_into_garage = "Appuyez sur ~INPUT_CONTEXT~ pour rentrer le ~b~véhicule de Police",
- help_text_get_car_out_garage = "Appuyez sur ~INPUT_CONTEXT~ pour sortir un ~b~véhicule de Police",
- help_text_put_heli_into_garage = "Appuyez sur ~INPUT_CONTEXT~ pour rentrer l'~b~hélicoptère de Police",
- help_text_get_heli_out_garage = "Appuyez sur ~INPUT_CONTEXT~ pour sortir un ~b~hélicoptère de Police",
- no_player_near_ped = "Aucun joueur à proximité",
- no_veh_near_ped = "Aucun véhicule à proximté",
- cop_whitelist_disabled = "La whitelist police est désactivée, veuillez l'activer pour utiliser cette commande !",
-
- menu_id_card_title = "Carte d'identité",
- menu_check_inventory_title = "Fouiller",
- menu_toggle_cuff_title = "(De)Menotter",
- menu_weapons_title = "Confisquer les armes",
- menu_force_player_get_in_car_title = "Mettre dans le véhicule",
- menu_force_player_get_out_car_title = "Faire sortir du véhicule",
- menu_drag_player_title = "Escorter le joueur",
- menu_fines_title = "Amendes",
- menu_check_plate_title = "Plaque d'immatriculation",
- menu_crochet_veh_title = "Crocheter le véhicule",
- menu_global_title = "Menu Police",
- menu_categories_title = "Categories",
- menu_animations_title = "Animations",
- menu_citizens_title = "Citoyens",
- menu_vehicles_title = "Véhicules",
- menu_close_menu_title = "Fermer le menu",
- menu_anim_do_traffic_title = "Faire la circulation",
- menu_anim_take_notes_title = "Prendre des notes",
- menu_anim_standby_title = "Repos",
- menu_anim_standby_2_title = "Repos 2",
- menu_anim_Cancel_emote_title = "Annuler emote",
- menu_custom_amount_fine_title = "Autre montant",
- menu_doing_traffic_notification = "~g~Vous faites la circulation.",
- menu_taking_notes_notification = "~g~Vous prenez des notes.",
- menu_being_stand_by_notification = "~g~Vous êtes en Stand By.",
- menu_veh_opened_notification = "Le véhicule est ~g~ouvert~w~.",
-
- menu_put_in_jail_title = "Put in jail",
- menu_arrest_title = "Arrest",
- menu_custom_amount_jail_title = "Custom amount in seconds",
- jail_notification_title = "^4[JAIL]",
- jail_arrest_notification_part_1 = "You got Arrested for ^1", -- send to the client after he got puted into the jail
- jail_arrest_notification_part_2 = " ^0seconds!",
- jail_weapons_removed = "Your Weapons got removed for being Arrested!",
- jail_not_cuffed = "Player need to be cuffed!",
- jail_remove_weapons_notification_part_1 = "All the weapons from ",
- jail_remove_weapons_notification_part_2 = " got removed.",
- menu_delete_vehicle_title = "Delete Vehicle",
-
- garage_global_title = "Garage de police",
- garage_loading = "~b~Chargement...",
-
- cloackroom_global_title = "Vestiaire Police",
- cloackroom_take_service_ranger_title = "Clock in as Park Ranger",
- cloackroom_take_service_sheriff_title = "Clock in as Sheriff",
- cloackroom_take_service_chp_title = "Clock in as State Trooper",
- cloackroom_take_service_prison_title = "Clock in as a Prison Guard",
- cloackroom_take_service_normal_title = "Prendre le service (uniforme)",
- cloackroom_take_service_hidden_title = "Prendre le service (BAC)",
- cloackroom_take_service_swat_title = "Prendre le service (intervention)",
- cloackroom_break_service_title = "Fin de service",
- cloackroom_add_bulletproof_vest_title = "Gilet par balle",
- cloackroom_remove_bulletproof_vest_title = "Enlever le Gilet par balle",
- cloackroom_add_yellow_vest_title = "Gilet jaune",
- cloackroom_remove_yellow_vest_title = "Enlever le Gilet jaune",
- now_in_service_notification = "Vous êtes maintenant ~g~En service",
- break_service_notification = "Vous avez ~r~terminé votre service",
- help_open_menu_notification = "Appuyer sur ~g~F5~w~ pour ouvrir le ~b~Menu Police",
-
- menu_props_title = "Objects",
- menu_spawn_props_title = "Placer un props",
- menu_spawn_barrier_title = "Spawn a police barrier",
- menu_spawn_work_ahead_barrier_title = "Spawn work ahead barrier",
- menu_remove_last_props_title = "Retirer le dernier props",
- menu_remove_all_props_title = "Retirer tous les props",
- removed_prop = "Object has been ~g~removed~w~.",
- removed_props = "Objects have been ~g~removed~w~.",
-
- vehicle_checking_plate_part_1 = "Le véhicule #", -- before number plate
- vehicle_checking_plate_part_2 = " appartient à ", -- between number plate and player name when veh registered
- vehicle_checking_plate_part_3 = "", -- after player name when veh registered
- vehicle_checking_plate_not_registered = " n'est pas enregistré !", -- after player name
- unseat_sender_notification_part_1 = "", -- before player name
- unseat_sender_notification_part_2 = " est sortie !", -- after player name
- drag_sender_notification_part_1 = "Escorte de ", -- before player name
- drag_sender_notification_part_2 = "", -- after player name
- checking_inventory_part_1 = "Items de ",
- checking_inventory_part_2 = " : ",
- checking_weapons_part_1 = "Armes de ",
- checking_weapons_part_2 = " : ",
- send_fine_request_part_1 = "Envoi d'une requête d'amende de $",
- send_fine_request_part_2 = " à ",
- already_have_a_pendind_fine_request = " à déjà une demande d'amende",
- request_fine_timeout = " n'a pas répondu à la demande d'amende",
- request_fine_refused = " à refusé son amende",
- request_fine_accepted = " à payé son amende",
- toggle_cuff_player_part_1 = "Tentative de mettre les menottes à ",
- toggle_cuff_player_part_2 = "",
- force_player_get_in_vehicle_part_1 = "Tentative de faire rentrer ",
- force_player_get_in_vehicle_part_2 = " dans le véhicule",
- usage_command_copadd = "Utilisation : /copadd [ID]",
- usage_command_coprem = "Utilisation : /coprem [ID]",
- usage_command_coprank = "Utilisation : /coprank [ID] [RANG]",
- command_received = "Compris !",
- become_cop_success = "Félicitation, vous êtes désormais policier !~w~.",
- remove_from_cops = "Vous n'êtes plus policier !~w~.",
- no_player_with_this_id = "Aucun joueur avec cet ID !",
- not_enough_permission = "Vous n'avez pas la permission de faire ça !",
- new_dept = "Congrats, you are now part of the",
- same_dept = "That's the same department!",
- new_rank = "Félicitation, vous êtes désormais : ",
- player_not_cop = "Ce joueur n'est pas un policier",
- rank_not_exist = "Ce grade n'existe pas",
- dept_not_exist = "This department doesn't exist",
- armory_global_title = "Armurerie de Police",
- help_text_open_armory = "Appuyez sur ~INPUT_CONTEXT~ pour ouvrir l'armurerie",
- armory_add_bulletproof_vest_title = "Mettre le gilet par-balle",
- armory_remove_bulletproof_vest_title = "Retirer le gilet par-balle",
- armory_weapons_list = "Choisir les armes",
- armory_basic_kit = "Kit police de base",
-})
\ No newline at end of file
diff --git a/resources/police/server/server.lua b/resources/police/server/server.lua
deleted file mode 100644
index d4c29fc36..000000000
--- a/resources/police/server/server.lua
+++ /dev/null
@@ -1,402 +0,0 @@
---[[
- Cops_FiveM - A cops script for FiveM RP servers.
- Copyright (C) 2018 FiveM-Scripts
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero 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 Affero General Public License for more details.
-You should have received a copy of the GNU Affero General Public License
-along with Cops_FiveM in the file "LICENSE". If not, see .
-]]
-
-
-if config.useCopWhitelist then
- local setupTable = "CREATE TABLE IF NOT EXISTS `police` (`identifier` varchar(255) COLLATE utf8_unicode_ci NOT NULL,`dept` int(11) NOT NULL DEFAULT '0',`rank` int(11) NOT NULL DEFAULT '0', `amount` int(11) NOT NULL DEFAULT '1000')"
- exports.ghmattimysql:execute(setupTable, {}, function()
- IsDatabaseVerified = true
- end)
-end
-
-if GetResourceMetadata(GetCurrentResourceName(), 'resource_Isdev', 0) == "yes" then
- RconPrint("/!\\ You are running a dev version of Cops FiveM !\n")
-end
-
-if config.enableVersionNotifier then
- PerformHttpRequest("https://raw.githubusercontent.com/FiveM-Scripts/Cops_FiveM/master/police/fxmanifest.lua", function(errorCode, result, headers)
- local version = GetResourceMetadata(GetCurrentResourceName(), 'version', 0)
-
- if string.find(tostring(result), version) == nil then
- print("\n\r[Cops_FiveM] The version on this server is not up to date. Please update now.\n\r")
- end
- end, "GET", "", "")
-end
-
-local inServiceCops = {}
-
-function addCop(identifier)
- exports.ghmattimysql:scalar("SELECT identifier FROM police WHERE identifier = @identifier", { ['identifier'] = tostring(identifier)}, function (result)
- if not result then
- exports.ghmattimysql:execute("INSERT INTO police (`identifier`) VALUES ('"..identifier.."')", {['@identifier'] = identifier})
- end
- end)
-end
-
-function setDept(source, player,playerDept)
- local identifier = getPlayerID(player)
- if(config.departments.label[playerDept]) then
- exports.ghmattimysql:execute("SELECT * FROM police WHERE identifier = '"..identifier.."'", { ['@identifier'] = identifier}, function (result)
- if(result[1]) then
- if(result[1].dept ~= playerDept) then
- exports.ghmattimysql:execute("UPDATE police SET dept="..playerDept.." WHERE identifier='"..identifier.."'", { ['identifier'] = identifier})
- TriggerClientEvent('chatMessage', source, i18n.translate("title_notification"), {255, 0, 0}, i18n.translate("command_received"))
- TriggerClientEvent("police:notify", player, "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, i18n.translate("new_dept") .. " " .. config.departments.label[playerDept])
- TriggerClientEvent('police:receiveIsCop', source, result[1].rank, playerDept)
- else
- TriggerClientEvent('chatMessage', source, i18n.translate("title_notification"), {255, 0, 0}, i18n.translate("same_dept"))
- end
- else
- TriggerClientEvent('chatMessage', source, i18n.translate("title_notification"), {255, 0, 0}, i18n.translate("player_not_cop"))
- end
- end)
- else
- TriggerClientEvent('chatMessage', source, i18n.translate("title_notification"), {255, 0, 0}, i18n.translate("dept_not_exist"))
- end
-end
-
-function remCop(identifier)
- exports.ghmattimysql:execute("DELETE FROM police WHERE identifier = '"..identifier.."'", { ['identifier'] = identifier})
-end
-
-AddEventHandler('playerDropped', function()
- if(inServiceCops[source]) then
- inServiceCops[source] = nil
-
- for i, c in pairs(inServiceCops) do
- TriggerClientEvent("police:resultAllCopsInService", i, inServiceCops)
- end
- end
-end)
-
-RegisterServerEvent('police:checkIsCop')
-AddEventHandler('police:checkIsCop', function()
- local identifier = getPlayerID(source)
- local src = source
-
- if config.useCopWhitelist then
- exports.ghmattimysql:scalar("SELECT `identifier` FROM police WHERE identifier = @identifier", { ['identifier'] = identifier}, function(result)
- if not result then
- TriggerClientEvent('police:receiveIsCop', src, -1)
- else
- exports.ghmattimysql:execute("SELECT * FROM police WHERE identifier = @identifier", { ['identifier'] = identifier}, function(data)
- if data then
- TriggerClientEvent('police:receiveIsCop', src, data[1].rank, data[1].dept)
- end
- end)
- end
- end)
- else
- TriggerClientEvent('police:receiveIsCop', src, 0, 1)
- end
-end)
-
-RegisterServerEvent('police:takeService')
-AddEventHandler('police:takeService', function()
-
- if(not inServiceCops[source]) then
- inServiceCops[source] = getPlayerID(source)
-
- for i, c in pairs(inServiceCops) do
- TriggerClientEvent("police:resultAllCopsInService", i, inServiceCops)
- end
- end
-end)
-
-RegisterServerEvent('police:breakService')
-AddEventHandler('police:breakService', function()
-
- if(inServiceCops[source]) then
- inServiceCops[source] = nil
-
- for i, c in pairs(inServiceCops) do
- TriggerClientEvent("police:resultAllCopsInService", i, inServiceCops)
- end
- end
-end)
-
-RegisterServerEvent('police:getAllCopsInService')
-AddEventHandler('police:getAllCopsInService', function()
- TriggerClientEvent("police:resultAllCopsInService", source, inServiceCops)
-end)
-
-RegisterServerEvent('police:removeWeapons')
-AddEventHandler('police:removeWeapons', function(target)
- local identifier = getPlayerID(target)
- TriggerClientEvent("police:removeWeapons", target)
-end)
-
-RegisterServerEvent('police:confirmUnseat')
-AddEventHandler('police:confirmUnseat', function(t)
- TriggerClientEvent("police:notify", source, "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, i18n.translate("unseat_sender_notification_part_1") .. GetPlayerName(t) .. i18n.translate("unseat_sender_notification_part_2"))
- TriggerClientEvent('police:unseatme', t)
-end)
-
-RegisterServerEvent('police:dragRequest')
-AddEventHandler('police:dragRequest', function(t)
- TriggerClientEvent("police:notify", source, "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, i18n.translate("drag_sender_notification_part_1").. GetPlayerName(t) .. i18n.translate("drag_sender_notification_part_2"))
- TriggerClientEvent('police:toggleDrag', t, source)
-end)
-
-RegisterServerEvent('police:finesGranted')
-AddEventHandler('police:finesGranted', function(target, amount)
- TriggerClientEvent('police:payFines', target, amount, source)
- TriggerClientEvent("police:notify", source, "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, i18n.translate("send_fine_request_part_1")..amount..i18n.translate("send_fine_request_part_2")..GetPlayerName(target))
-end)
-
-RegisterServerEvent('police:finesETA')
-AddEventHandler('police:finesETA', function(officer, code)
- if(code==1) then
- TriggerClientEvent("police:notify", officer, "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, GetPlayerName(source)..i18n.translate("already_have_a_pendind_fine_request"))
- elseif(code==2) then
- TriggerClientEvent("police:notify", officer, "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, GetPlayerName(source)..i18n.translate("request_fine_timeout"))
- elseif(code==3) then
- TriggerClientEvent("police:notify", officer, "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, GetPlayerName(source)..i18n.translate("request_fine_refused"))
- elseif(code==0) then
- TriggerClientEvent("police:notify", officer, "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, GetPlayerName(source)..i18n.translate("request_fine_accepted"))
- end
-end)
-
-RegisterServerEvent('police:cuffGranted')
-AddEventHandler('police:cuffGranted', function(t)
- TriggerClientEvent("police:notify", source, "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, i18n.translate("toggle_cuff_player_part_1")..GetPlayerName(t)..i18n.translate("toggle_cuff_player_part_2"))
- TriggerClientEvent('police:getArrested', t)
-end)
-
-RegisterServerEvent('police:forceEnterAsk')
-AddEventHandler('police:forceEnterAsk', function(t, v)
- TriggerClientEvent("police:notify", source, "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, i18n.translate("force_player_get_in_vehicle_part_1")..GetPlayerName(t)..i18n.translate("force_player_get_in_vehicle_part_2"))
- TriggerClientEvent('police:forcedEnteringVeh', t, v)
-end)
-
-RegisterServerEvent('CheckPoliceVeh')
-AddEventHandler('CheckPoliceVeh', function(vehicle)
- TriggerClientEvent('FinishPoliceCheckForVeh',source)
- TriggerClientEvent('policeveh:spawnVehicle', source, vehicle)
-end)
-
-RegisterServerEvent('police:GetPayChecks')
-AddEventHandler('police:GetPayChecks', function(t)
- local identifier = getPlayerID(source)
- local src = source
-
- exports.ghmattimysql:scalar("SELECT `amount` FROM police WHERE identifier = @identifier", { ['identifier'] = identifier}, function(result)
- if result then
- data = json.encode(result)
- print(data)
- TriggerClientEvent('police:receivePaycheck', src, data)
- end
- end)
-end)
-
-RegisterServerEvent('police:TransferPayCheck')
-AddEventHandler('police:TransferPayCheck', function(t)
- local identifier = getPlayerID(source)
- local src = source
-
- exports.ghmattimysql:scalar("SELECT `amount` FROM police WHERE identifier = @identifier", { ['identifier'] = identifier}, function(result)
- if result then
- data = json.encode(result)
- salary = config.weekly_salary + tonumber(data)
- local values = { "police", "amount", salary, { ["identifier"] = identifier } }
- exports.ghmattimysql:execute("UPDATE ?? SET ?? = ? WHERE ?", values, function(data)
- if data then
- TriggerClientEvent('police:receivePaycheck', src, salary)
- end
- end)
- end
- end)
-end)
-
---RegisterServerEvent('police:UpdateNotifier')
---AddEventHandler('police:UpdateNotifier', function()
--- local src = source
--- PerformHttpRequest("https://raw.githubusercontent.com/FiveM-Scripts/Cops_FiveM/master/police/__resource.lua", function(errorCode, result, headers)
--- local version = GetResourceMetadata(GetCurrentResourceName(), 'resource_version', 0)
--- if string.find(tostring(result), version) == nil then
--- TriggerClientEvent('police:Update', src, true)
--- end
--- end, "GET", "", "")
---end)
-
-RegisterCommand("CopAddAdmin", function(source,args,raw)
- if #args ~= 1 then
- RconPrint("Usage: CopAddAdmin [ingame-id]\n")
- CancelEvent()
- return
- else
- local maxi = -1
- for key, value in pairs(config.rank.label) do
- if key > maxi then
- maxi = key
- end
- end
-
- if(GetPlayerName(tonumber(args[1])) == nil)then
- RconPrint("Player is not ingame\n")
- CancelEvent()
-
- return
- end
-
- local identifier = getPlayerID(tonumber(args[1]))
- exports.ghmattimysql:scalar("SELECT identifier FROM police WHERE identifier = @identifier", {['identifier'] = identifier}, function(result)
- if not result then
- exports.ghmattimysql:execute("INSERT INTO police (`identifier`, `dept`, `rank`) VALUES (@identifier, @dept, @maxi)", { ['identifier'] = identifier, ['dept'] = 1, ['maxi'] = maxi})
- TriggerClientEvent("police:notify", tonumber(args[1]), "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, i18n.translate("become_cop_success"))
-
- RconPrint(GetPlayerName(tonumber(args[1])) .. " is now added to the police database.\n")
- TriggerClientEvent('police:receiveIsCop', tonumber(args[1]), maxi, 1)
- else
- RconPrint(GetPlayerName(tonumber(args[1])) .. ' already exists.\n')
- end
- end)
- CancelEvent()
- end
-end, true)
-
-RegisterCommand("CopAdd", function(source,args,raw)
- if #args ~= 1 then
- RconPrint("Usage: CopAdd [ingame-id]\n")
- CancelEvent()
- return
- else
- if GetPlayerName(tonumber(args[1])) == nil then
- RconPrint("Player is not ingame\n")
- CancelEvent()
- return
- end
-
- local identifier = getPlayerID(tonumber(args[1]))
- exports.ghmattimysql:scalar("SELECT identifier FROM police WHERE identifier = @identifier", { ['identifier'] = identifier}, function (result)
- if not result then
- print('Adding record for player to the database')
- addCop(identifier)
-
- TriggerClientEvent("police:notify", tonumber(args[1]), "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, i18n.translate("become_cop_success"))
- TriggerClientEvent('police:receiveIsCop', tonumber(args[1]), 0, 1)
-
- RconPrint(GetPlayerName(tonumber(args[1])) .. " is now added to the police database.\n")
- else
- RconPrint(GetPlayerName(tonumber(args[1])) .. " is already a police officer.\n")
- end
- end)
- end
-end, true)
-
-RegisterCommand("CopRem", function(source,args,raw)
- if #args ~= 1 then
- RconPrint("Usage: CopRem [ingame-id]\n")
- CancelEvent()
- return
- else
- if(GetPlayerName(tonumber(args[1])) == nil)then
- RconPrint("Player is not ingame\n")
- CancelEvent()
- return
- end
-
- local identifier = getPlayerID(tonumber(args[1]))
-
- exports.ghmattimysql:scalar("SELECT identifier FROM police WHERE identifier = @identifier", { ['identifier'] = identifier}, function (result)
- if not result then
- RconPrint(GetPlayerName(tonumber(args[1])) .. " isn't here.\n")
- else
- exports.ghmattimysql:execute("DELETE FROM police WHERE identifier = @identifier", { ['identifier'] = identifier})
- TriggerClientEvent('police:noLongerCop', tonumber(args[1]))
- TriggerClientEvent("police:notify", tonumber(args[1]), "CHAR_AGENT14", 1, i18n.translate("title_notification"), false, i18n.translate("remove_from_cops"))
- RconPrint(GetPlayerName(tonumber(args[1])) .. " is now removed from the police database.\n")
- end
- end)
-
- CancelEvent()
- end
-end, true)
-
-RegisterCommand("CopRank", function(source,args,raw)
- if #args ~= 2 then
- RconPrint("Usage: CopRank [ingame-id] [rank]\n")
- CancelEvent()
- return
- elseif(not config.rank.label[tonumber(args[2])]) then
- RconPrint("You have to enter a valid rank !\n")
- CancelEvent()
- return
- else
- if(GetPlayerName(tonumber(args[1])) == nil)then
- RconPrint("Player is not ingame\n")
- CancelEvent()
- return
- end
-
- local identifier = getPlayerID(tonumber(args[1]))
- exports.ghmattimysql:scalar("SELECT `identifier` FROM police WHERE identifier = @identifier", { ['identifier'] = identifier}, function (rank)
- if(rank == nil) then
- RconPrint(GetPlayerName(tonumber(args[1])) .. " isn't here.\n")
- else
- exports.ghmattimysql:execute("UPDATE police SET `rank` = @rank WHERE identifier = @identifier", { ['identifier'] = identifier, ['rank'] = args[2]})
- TriggerClientEvent('police:receiveIsCop', tonumber(args[1]), tonumber(args[2]))
- RconPrint(GetPlayerName(tonumber(args[1])) .. " information has been updated.\n")
- end
- end)
-
- CancelEvent()
- end
-end, true)
-
-RegisterCommand("CopDept", function(source,args,raw)
- if #args ~= 2 then
- RconPrint("Usage: CopDept [ingame-id] [department]\n")
- CancelEvent()
- return
- else
- if(GetPlayerName(tonumber(args[1])) == nil) then
- RconPrint("Player is not ingame\n")
- CancelEvent()
- return
- end
-
- local identifier = getPlayerID(tonumber(args[1]))
- exports.ghmattimysql:scalar("SELECT `identifier` FROM police WHERE identifier = @identifier", { ['identifier'] = identifier}, function (result)
- if result then
- if GetPlayerName(tonumber(args[1])) ~= nil then
- local player = tonumber(args[1])
- local dept = tonumber(args[2])
-
- setDept(args[1], player, dept)
- else
- TriggerClientEvent('chatMessage', args[1], i18n.translate("title_notification"), {255, 0, 0}, i18n.translate("no_player_with_this_id"))
- end
- else
- TriggerClientEvent('chatMessage', args[1], i18n.translate("title_notification"), {255, 0, 0}, i18n.translate("not_enough_permission"))
- end
- end)
-
- CancelEvent()
- end
-end, true)
-
-function getPlayerID(source)
- local identifiers = GetPlayerIdentifiers(source)
- local player = getIdentifiant(identifiers)
- return player
-end
-
-function getIdentifiant(id)
- for _, v in ipairs(id) do
- return v
- end
-end
diff --git a/resources/vMenu/vmenu.log b/resources/vMenu/vmenu.log
index a47e5717e..792744f41 100644
--- a/resources/vMenu/vmenu.log
+++ b/resources/vMenu/vmenu.log
@@ -4,3 +4,7 @@
[ 03-09-2024 05:30:49 ] [KICK ACTION] Player: ~r~ ¦ 1A-80 has kicked: 227 | Adam | Senior Officer for: You have been kicked. Reason: VDM x2.
[ 03-09-2024 06:44:32 ] [KICK ACTION] Player: ~r~ ¦ 1A-80 has kicked: 227 | Adam | Senior Officer for: You have been kicked. Reason: .
[ 03-09-2024 07:06:41 ] [KICK ACTION] Player: ~r~ ¦ 1A-80 has kicked: 227 | Adam | Senior Officer for: You have been kicked. Reason: RDM x2.
+[ 08-09-2024 03:11:38 ] [BAN ACTION] A new ban record has been added. Player: 'Brzzy' was banned by '[197]Max Rod' for 'Banned by staff. good job
+Your ban id: afd274e2-146e-4407-b68a-34f0edf1c24c' until '09/09/2024 09:11:38'.
+[ 08-09-2024 03:27:19 ] [BAN ACTION] The following ban record has been removed (player unbanned). [Player: Brzzy was banned by [197]Max Rod for Banned by staff. good job
+Your ban id: afd274e2-146e-4407-b68a-34f0edf1c24c until 09/09/2024 09:11:38.]
diff --git a/server.cfg b/server.cfg
index da97e9587..3ee0b57c6 100644
--- a/server.cfg
+++ b/server.cfg
@@ -46,7 +46,6 @@ ensure Head-Tags
setr SCREENSHOT_BASIC_TOKEN 9dfc22d9d7a9ff2
-ensure ghmattimysql
ensure mysql-async
ensure oxmysql
@@ -54,7 +53,7 @@ set mysql_connection_string "server=localhost;uid=root;password=Elite_Gaming_13;
//set mysql_connection_string "server=localhost;uid=root;password=Elite_Gaming_13;database=elitebot"
#[-----Scripts With MySQL-----]
-ensure police
+ensure Interaction-Menu
ensure screenshot-basic
ensure pma-voice
setr voice_defaultCycle "57"
@@ -560,4 +559,9 @@ add_ace group.helper jd.staff allow
add_ace group.superadmin hypnonema allow
add_ace group.admin hypnonema allow
add_ace group.moderator hypnonema allow
-add_ace group.helper hypnonema allow
\ No newline at end of file
+add_ace group.helper hypnonema allow
+
+add_ace builtin.everyone sem_intmenu.leo allow
+add_ace builtin.everyone sem_intmenu.fire allow
+add_ace group.helper sem_intmenu.unjail allow
+add_ace group.helper sem_intmenu.unhospital allow
\ No newline at end of file