From d95b960b4d1da4fd4af14ae20775b2848f591840 Mon Sep 17 00:00:00 2001 From: KingMcDonalds Date: Sat, 15 Nov 2025 09:09:43 -0800 Subject: [PATCH] adding lvc --- .../hane_41_house_modern/desktop.ini | 2 - resources/[EGRP-Map-Addons]/lvc/LICENSE | 674 ++++++++ resources/[EGRP-Map-Addons]/lvc/LICENSE.html | 694 ++++++++ resources/[EGRP-Map-Addons]/lvc/SETTINGS.lua | 75 + resources/[EGRP-Map-Addons]/lvc/SIRENS.lua | 1501 +++++++++++++++++ .../[EGRP-Map-Addons]/lvc/UTIL/cl_lvc.lua | 861 ++++++++++ .../[EGRP-Map-Addons]/lvc/UTIL/cl_storage.lua | 415 +++++ .../[EGRP-Map-Addons]/lvc/UTIL/cl_utils.lua | 434 +++++ .../[EGRP-Map-Addons]/lvc/UTIL/semver.lua | 232 +++ .../[EGRP-Map-Addons]/lvc/UTIL/sv_lvc.lua | 190 +++ .../[EGRP-Map-Addons]/lvc/fxmanifest.lua | 86 + resources/[EGRP-Map-Addons]/lvc/version | 1 + 12 files changed, 5163 insertions(+), 2 deletions(-) delete mode 100644 resources/[EGRP-Map-Addons]/hane_41_house_modern/desktop.ini create mode 100644 resources/[EGRP-Map-Addons]/lvc/LICENSE create mode 100644 resources/[EGRP-Map-Addons]/lvc/LICENSE.html create mode 100644 resources/[EGRP-Map-Addons]/lvc/SETTINGS.lua create mode 100644 resources/[EGRP-Map-Addons]/lvc/SIRENS.lua create mode 100644 resources/[EGRP-Map-Addons]/lvc/UTIL/cl_lvc.lua create mode 100644 resources/[EGRP-Map-Addons]/lvc/UTIL/cl_storage.lua create mode 100644 resources/[EGRP-Map-Addons]/lvc/UTIL/cl_utils.lua create mode 100644 resources/[EGRP-Map-Addons]/lvc/UTIL/semver.lua create mode 100644 resources/[EGRP-Map-Addons]/lvc/UTIL/sv_lvc.lua create mode 100644 resources/[EGRP-Map-Addons]/lvc/fxmanifest.lua create mode 100644 resources/[EGRP-Map-Addons]/lvc/version diff --git a/resources/[EGRP-Map-Addons]/hane_41_house_modern/desktop.ini b/resources/[EGRP-Map-Addons]/hane_41_house_modern/desktop.ini deleted file mode 100644 index 11aa9593e..000000000 --- a/resources/[EGRP-Map-Addons]/hane_41_house_modern/desktop.ini +++ /dev/null @@ -1,2 +0,0 @@ -[.ShellClassInfo] -IconResource=C:\Program Files\Google\Drive File Stream\108.0.1.0\GoogleDriveFS.exe,26 diff --git a/resources/[EGRP-Map-Addons]/lvc/LICENSE b/resources/[EGRP-Map-Addons]/lvc/LICENSE new file mode 100644 index 000000000..f288702d2 --- /dev/null +++ b/resources/[EGRP-Map-Addons]/lvc/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/[EGRP-Map-Addons]/lvc/LICENSE.html b/resources/[EGRP-Map-Addons]/lvc/LICENSE.html new file mode 100644 index 000000000..5b633d968 --- /dev/null +++ b/resources/[EGRP-Map-Addons]/lvc/LICENSE.html @@ -0,0 +1,694 @@ + + + + + GNU General Public License v3.0 - GNU Project - Free Software Foundation (FSF) + + + +

GNU GENERAL PUBLIC LICENSE

+

Version 3, 29 June 2007

+ +

Copyright © 2007 Free Software Foundation, Inc. + <https://fsf.org/>

+ Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed.

+ +

Preamble

+ +

The GNU General Public License is a free, copyleft license for +software and other kinds of works.

+ +

The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too.

+ +

When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things.

+ +

To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others.

+ +

For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights.

+ +

Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it.

+ +

For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions.

+ +

Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users.

+ +

Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free.

+ +

The precise terms and conditions for copying, distribution and +modification follow.

+ +

TERMS AND CONDITIONS

+ +
0. Definitions.
+ +

“This License” refers to version 3 of the GNU General Public License.

+ +

“Copyright” also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks.

+ +

“The Program” refers to any copyrightable work licensed under this +License. Each licensee is addressed as “you”. “Licensees” and +“recipients” may be individuals or organizations.

+ +

To “modify” a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a “modified version” of the +earlier work or a work “based on” the earlier work.

+ +

A “covered work” means either the unmodified Program or a work based +on the Program.

+ +

To “propagate” a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well.

+ +

To “convey” a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying.

+ +

An interactive user interface displays “Appropriate Legal Notices” +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion.

+ +
1. Source Code.
+ +

The “source code” for a work means the preferred form of the work +for making modifications to it. “Object code” means any non-source +form of a work.

+ +

A “Standard Interface” means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language.

+ +

The “System Libraries” of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +“Major Component”, in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it.

+ +

The “Corresponding Source” for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work.

+ +

The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source.

+ +

The Corresponding Source for a work in source code form is that +same work.

+ +
2. Basic Permissions.
+ +

All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law.

+ +

You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you.

+ +

Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary.

+ +
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+ +

No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures.

+ +

When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures.

+ +
4. Conveying Verbatim Copies.
+ +

You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program.

+ +

You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee.

+ +
5. Conveying Modified Source Versions.
+ +

You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions:

+ +
    +
  • a) The work must carry prominent notices stating that you modified + it, and giving a relevant date.
  • + +
  • b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + “keep intact all notices”.
  • + +
  • c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it.
  • + +
  • d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so.
  • +
+ +

A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +“aggregate” if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate.

+ +
6. Conveying Non-Source Forms.
+ +

You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways:

+ +
    +
  • a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange.
  • + +
  • b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge.
  • + +
  • c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b.
  • + +
  • d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements.
  • + +
  • e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d.
  • +
+ +

A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work.

+ +

A “User Product” is either (1) a “consumer product”, which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, “normally used” refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product.

+ +

“Installation Information” for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made.

+ +

If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM).

+ +

The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network.

+ +

Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying.

+ +
7. Additional Terms.
+ +

“Additional permissions” are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions.

+ +

When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission.

+ +

Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms:

+ +
    +
  • a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or
  • + +
  • b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or
  • + +
  • c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or
  • + +
  • d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or
  • + +
  • e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or
  • + +
  • f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors.
  • +
+ +

All other non-permissive additional terms are considered “further +restrictions” within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying.

+ +

If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms.

+ +

Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way.

+ +
8. Termination.
+ +

You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11).

+ +

However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation.

+ +

Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice.

+ +

Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10.

+ +
9. Acceptance Not Required for Having Copies.
+ +

You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so.

+ +
10. Automatic Licensing of Downstream Recipients.
+ +

Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License.

+ +

An “entity transaction” is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts.

+ +

You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it.

+ +
11. Patents.
+ +

A “contributor” is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's “contributor version”.

+ +

A contributor's “essential patent claims” are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, “control” includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License.

+ +

Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version.

+ +

In the following three paragraphs, a “patent license” is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To “grant” such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party.

+ +

If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. “Knowingly relying” means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid.

+ +

If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it.

+ +

A patent license is “discriminatory” if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007.

+ +

Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law.

+ +
12. No Surrender of Others' Freedom.
+ +

If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program.

+ +
13. Use with the GNU Affero General Public License.
+ +

Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such.

+ +
14. Revised Versions of this License.
+ +

The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns.

+ +

Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License “or any later version” applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation.

+ +

If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program.

+ +

Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version.

+ +
15. Disclaimer of Warranty.
+ +

THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

+ +
16. Limitation of Liability.
+ +

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES.

+ +
17. Interpretation of Sections 15 and 16.
+ +

If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee.

+ +

END OF TERMS AND CONDITIONS

+ +

How to Apply These Terms to Your New Programs

+ +

If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms.

+ +

To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the “copyright” line and a pointer to where the full notice is found.

+ +
    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+ +

Also add information on how to contact you by electronic and paper mail.

+ +

If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode:

+ +
    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+ +

The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an “about box”.

+ +

You should also get your employer (if you work as a programmer) or school, +if any, to sign a “copyright disclaimer” for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<https://www.gnu.org/licenses/>.

+ +

The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<https://www.gnu.org/licenses/why-not-lgpl.html>.

+ + + \ No newline at end of file diff --git a/resources/[EGRP-Map-Addons]/lvc/SETTINGS.lua b/resources/[EGRP-Map-Addons]/lvc/SETTINGS.lua new file mode 100644 index 000000000..729bd9dda --- /dev/null +++ b/resources/[EGRP-Map-Addons]/lvc/SETTINGS.lua @@ -0,0 +1,75 @@ +--------------------COMMUNITY ID------------------- +community_id = 'EGRP' +-- Sets a prefix for saved values at the user end, without this people who play on multiple LVC server could face conflicts. **Once set DO NOT CHANGE. It will result in loss of data for end users.** +-- I recommend something short (4-6 characters) for example a community abbreviation. SPACES ARE NOT ALLOWED. + +------------------MENU KEYBINDING------------------ +open_menu_key = 'O' +-- Sets default key for RegisterKeyMapping. Examples: 'l','F5', etc. DEFAULT: 'O', users may set one in their GTA V > Settings > Hotkeys > FiveM settings. +-- More info: https://cookbook.fivem.net/2020/01/06/using-the-new-console-key-bindings/ +-- List of Keys: https://pastebin.com/u9ewvWWZ + + +---------------LOCKOUT FUNCTIONALITY--------------- +lockout_default_hotkey = '' +-- Sets default key for RegisterKeyMapping. Examples: 'l','F5', etc. DEFAULT: NONE, users may set one in their GTA V > Settings > Hotkeys > FiveM settings. +-- More info: https://cookbook.fivem.net/2020/01/06/using-the-new-console-key-bindings/ +-- List of Keys: https://pastebin.com/u9ewvWWZ +locked_press_count = 5 +-- Initial press count for reminder e.g. if this is 5 and reminder_rate is 10 then, after 5 key presses it will remind you the first time, after that every 10 key presses. +reminder_rate = 10 +-- How often, in luxart key presses, to remind you that your siren controller is locked. + +-----------------HUD FUNCTIONALITY----------------- +hud_first_default = true +-- First state of HUD, otherwise it uses the players KVP setting (previous state). + +---------------MAIN SIREN SETTINGS----------------- +main_siren_settings_masterswitch = true +-- Enables users to rename siren tones, change siren options. (Cycle / Button) +park_kill_masterswitch = true +-- Enables park kill functionality. Setting this to false will not allow users to change from default behaviour this. +park_kill_default = true +-- Default setting for park kill mode. (default: true) +airhorn_interrupt_masterswitch = true +-- Enables ability to toggle air horn interrupt. Setting this to false will not allow users to change from default behaviour this. +airhorn_interrupt_default = true +-- Default setting of the airhorn interrupt for the main siren. (default: true) +reset_to_standby_masterswitch = true +-- Enables ability to toggle reset to standby. Setting this to false will not allow users to change from default behaviour this. +reset_to_standby_default = true +-- Default setting for Reset-To-Standby functionality. (default: true) + +--------------CUSTOM MANU/HORN/SIREN--------------- +custom_manual_tones_master_switch = true +-- Enables manual tone settings menu items to change which tone is played for the primary and secondary manual tones. +custom_aux_tones_master_switch = true +-- Enables auxiliary tone settings menu item so players can change which tone is played when AUX siren (Up-Arrow) is enabled. +main_siren_set_register_keys_set_defaults = true +-- Enables RegisterKeyMapping for all main_allowed_tones and sets the default keys to numrow 1-0. + + +--------------TURN SIGNALS / HAZARDS--------------- +hazard_key = 202 +left_signal_key = 84 +right_signal_key = 83 +hazard_hold_duration = 750 +-- Time in milliseconds backspace must be pressed to turn on / off hazard lights. + + +----------------SOUND EFFECT VOLUMES--------------- +button_sfx_scheme_choices = { 'SSP2000', 'SSP3000', 'Cencom', 'CHP' } +--Customize which button SFX schemes are available. An item here must match exactly the folder name located in `lvc\UI\sounds`, recommend NOT using spaces instead use a dash (e.g. Cencom-Gold) +default_sfx_scheme_name = 'SSP2000' +default_on_volume = 0.5 +default_off_volume = 0.7 +default_upgrade_volume = 0.5 +default_downgrade_volume = 0.7 +default_hazards_volume = 0.09 +default_lock_volume = 0.25 +default_lock_reminder_volume = 0.2 +default_reminder_volume = 0.09 + + +------------------PLUG-IN SUPPORT------------------ +plugins_installed = true \ No newline at end of file diff --git a/resources/[EGRP-Map-Addons]/lvc/SIRENS.lua b/resources/[EGRP-Map-Addons]/lvc/SIRENS.lua new file mode 100644 index 000000000..9dab23c37 --- /dev/null +++ b/resources/[EGRP-Map-Addons]/lvc/SIRENS.lua @@ -0,0 +1,1501 @@ +--[[ +--------------------------------------------------- +LUXART VEHICLE CONTROL V3 (FOR FIVEM) +--------------------------------------------------- +Coded by Lt.Caine +ELS Clicks by Faction +Additions by TrevorBarns +--------------------------------------------------- +FILE: SIRENS.lua +PURPOSE: Associate specific sirens with specific +vehicles. Siren assignments. +--------------------------------------------------- +SIREN TONE TABLE: + ID- Generic Name (SIREN STRING) [vehicles.awc name] + 1 - Airhorn (SIRENS_AIRHORN) [AIRHORN_EQD] + 2 - Wail (VEHICLES_HORNS_SIREN_1) [SIREN_PA20A_WAIL] + 3 - Yelp (VEHICLES_HORNS_SIREN_2) [SIREN_2] + 4 - Priority (VEHICLES_HORNS_POLICE_WARNING) [POLICE_WARNING] + 5 - CustomA* (RESIDENT_VEHICLES_SIREN_WAIL_01) [SIREN_WAIL_01] + 6 - CustomB* (RESIDENT_VEHICLES_SIREN_WAIL_02) [SIREN_WAIL_02] + 7 - CustomC* (RESIDENT_VEHICLES_SIREN_WAIL_03) [SIREN_WAIL_03] + 8 - CustomD* (RESIDENT_VEHICLES_SIREN_QUICK_01) [SIREN_QUICK_01] + 9 - CustomE* (RESIDENT_VEHICLES_SIREN_QUICK_02) [SIREN_QUICK_02] + 10 - CustomF* (RESIDENT_VEHICLES_SIREN_QUICK_03) [SIREN_QUICK_03] + 11 - Powercall (VEHICLES_HORNS_AMBULANCE_WARNING) [AMBULANCE_WARNING] + 12 - FireHorn (VEHICLES_HORNS_FIRETRUCK_WARNING) [FIRE_TRUCK_HORN] + 13 - Firesiren (RESIDENT_VEHICLES_SIREN_FIRETRUCK_WAIL_01) [SIREN_FIRETRUCK_WAIL_01] + 14 - Firesiren2 (RESIDENT_VEHICLES_SIREN_FIRETRUCK_QUICK_01) [SIREN_FIRETRUCK_QUICK_01] +]] + +RequestScriptAudioBank('DLC_SERVERSIDEAUDIO\\OISS_SSA_VEHAUD_LSPD_NEW', false) +RequestScriptAudioBank('DLC_SERVERSIDEAUDIO\\OISS_SSA_VEHAUD_LSSD_NEW', false) +RequestScriptAudioBank('DLC_SERVERSIDEAUDIO\\OISS_SSA_VEHAUD_BCSO_NEW', false) +RequestScriptAudioBank('DLC_SERVERSIDEAUDIO\\OISS_SSA_VEHAUD_SAHP_NEW', false) +RequestScriptAudioBank('DLC_SERVERSIDEAUDIO\\OISS_SSA_VEHAUD_FIB_NEW', false) +RequestScriptAudioBank('DLC_SERVERSIDEAUDIO\\OISS_SSA_VEHAUD_LSFD_NEW', false) +RequestScriptAudioBank('DLC_SERVERSIDEAUDIO\\OISS_SSA_VEHAUD_BCFD_NEW', false) +RequestScriptAudioBank('DLC_SERVERSIDEAUDIO\\OISS_SSA_VEHAUD_LSSD_OLD', false) +RequestScriptAudioBank('DLC_SERVERSIDEAUDIO\\OISS_SSA_VEHAUD_SAHP_OLD', false) +RequestScriptAudioBank('DLC_SERVERSIDEAUDIO\\OISS_SSA_VEHAUD_LSFD_OLD', false) +RequestScriptAudioBank('DLC_SERVERSIDEAUDIO\\OISS_SSA_VEHAUD_RHPD_OLD', false) + +-- CHANGE SIREN NAMES, AUDIONAME, AUDIOREF +SIRENS = { +--[[1]] { Name = 'Airhorn', String = 'SIRENS_AIRHORN', Ref = 0 }, +--[[2]] { Name = 'Wail', String = 'VEHICLES_HORNS_SIREN_1', Ref = 0 }, +--[[3]] { Name = 'Yelp', String = 'VEHICLES_HORNS_SIREN_2', Ref = 0 }, +--[[4]] { Name = 'Priority', String = 'VEHICLES_HORNS_POLICE_WARNING', Ref = 0 }, +--[[5]] { Name = 'CustomA', String = 'RESIDENT_VEHICLES_SIREN_WAIL_01', Ref = 0 }, +--[[6]] { Name = 'CustomB', String = 'RESIDENT_VEHICLES_SIREN_WAIL_02', Ref = 0 }, +--[[7]] { Name = 'CustomA', String = 'RESIDENT_VEHICLES_SIREN_WAIL_03', Ref = 0 }, +--[[8]] { Name = 'CustomA', String = 'RESIDENT_VEHICLES_SIREN_QUICK_01', Ref = 0 }, +--[[9]] { Name = 'CustomA', String = 'RESIDENT_VEHICLES_SIREN_QUICK_02', Ref = 0 }, +--[[10]] { Name = 'CustomA', String = 'RESIDENT_VEHICLES_SIREN_QUICK_03', Ref = 0 }, +--[[11]] { Name = 'CustomA', String = 'VEHICLES_HORNS_AMBULANCE_WARNING', Ref = 0 }, +--[[12]] { Name = 'FireHorn', String = 'VEHICLES_HORNS_FIRETRUCK_WARNING', Ref = 0 }, +--[[13]] { Name = 'Fire Yelp', String = 'RESIDENT_VEHICLES_SIREN_FIRETRUCK_WAIL_01', Ref = 0 }, +--[[14]] { Name = 'Fire Yelp', String = 'RESIDENT_VEHICLES_SIREN_FIRETRUCK_QUICK_01', Ref = 0 }, +-- START OF SAS -- +--[[15]] { Name = '295-HORN', String = 'OISS_SSA_VEHAUD_LSPD_NEW_HORN', Ref = 'OISS_SSA_VEHAUD_LSPD_NEW_SOUNDSET'}, +--[[16]] { Name = '295-WAIL', String = 'OISS_SSA_VEHAUD_LSPD_NEW_SIREN_ADAM', Ref = 'OISS_SSA_VEHAUD_LSPD_NEW_SOUNDSET'}, +--[[17]] { Name = '295-YELP', String = 'OISS_SSA_VEHAUD_LSPD_NEW_SIREN_BOY', Ref = 'OISS_SSA_VEHAUD_LSPD_NEW_SOUNDSET'}, +--[[18]] { Name = '295-PIERCER', String = 'OISS_SSA_VEHAUD_LSPD_NEW_SIREN_CHARLES', Ref = 'OISS_SSA_VEHAUD_LSPD_NEW_SOUNDSET'}, +--[[19]] { Name = '295-SWEEP', String = 'OISS_SSA_VEHAUD_LSPD_NEW_SIREN_DAVID', Ref = 'OISS_SSA_VEHAUD_LSPD_NEW_SOUNDSET'}, +--[[20]] { Name = '295-HETRO', String = 'OISS_SSA_VEHAUD_LSPD_NEW_SIREN_EDWARD', Ref = 'OISS_SSA_VEHAUD_LSPD_NEW_SOUNDSET', Option = 3}, +--[[21]] { Name = 'HP-HORN', String = 'OISS_SSA_VEHAUD_LSSD_NEW_HORN', Ref = 'OISS_SSA_VEHAUD_LSSD_NEW_SOUNDSET'}, +--[[22]] { Name = 'HP-WAIL', String = 'OISS_SSA_VEHAUD_LSSD_NEW_SIREN_ADAM', Ref = 'OISS_SSA_VEHAUD_LSSD_NEW_SOUNDSET'}, +--[[23]] { Name = 'HP-YELP', String = 'OISS_SSA_VEHAUD_LSSD_NEW_SIREN_BOY', Ref = 'OISS_SSA_VEHAUD_LSSD_NEW_SOUNDSET'}, +--[[24]] { Name = 'HP-Evac', String = 'OISS_SSA_VEHAUD_LSSD_NEW_SIREN_CHARLES', Ref = 'OISS_SSA_VEHAUD_LSSD_NEW_SOUNDSET'}, +--[[25]] { Name = 'FS-WAIL (RBLR)', String = 'OISS_SSA_VEHAUD_LSSD_NEW_SIREN_DAVID', Ref = 'OISS_SSA_VEHAUD_LSSD_NEW_SOUNDSET', Option = 3}, +--[[26]] { Name = 'FS-YELP (RBLR)', String = 'OISS_SSA_VEHAUD_LSSD_NEW_SIREN_EDWARD', Ref = 'OISS_SSA_VEHAUD_LSSD_NEW_SOUNDSET'}, +--[[27]] { Name = 'TMD-HORN', String = 'OISS_SSA_VEHAUD_BCSO_NEW_HORN', Ref = 'OISS_SSA_VEHAUD_BCSO_NEW_SOUNDSET'}, +--[[28]] { Name = 'TMD-WAIL', String = 'OISS_SSA_VEHAUD_BCSO_NEW_SIREN_ADAM', Ref = 'OISS_SSA_VEHAUD_BCSO_NEW_SOUNDSET'}, +--[[29]] { Name = 'TMD-YELP', String = 'OISS_SSA_VEHAUD_BCSO_NEW_SIREN_BOY', Ref = 'OISS_SSA_VEHAUD_BCSO_NEW_SOUNDSET'}, +--[[30]] { Name = 'TMD-HETRO', String = 'OISS_SSA_VEHAUD_BCSO_NEW_SIREN_CHARLES', Ref = 'OISS_SSA_VEHAUD_BCSO_NEW_SOUNDSET'}, +--[[31]] { Name = 'TMD-SWEEP', String = 'OISS_SSA_VEHAUD_BCSO_NEW_SIREN_DAVID', Ref = 'OISS_SSA_VEHAUD_BCSO_NEW_SOUNDSET'}, +--[[32]] { Name = 'TMD-ULTRA HI-LO', String = 'OISS_SSA_VEHAUD_BCSO_NEW_SIREN_EDWARD', Ref = 'OISS_SSA_VEHAUD_BCSO_NEW_SOUNDSET', Option = 3}, +--[[33]] { Name = 'MCB-HORN', String = 'OISS_SSA_VEHAUD_SAHP_NEW_HORN', Ref = 'OISS_SSA_VEHAUD_SAHP_NEW_SOUNDSET'}, +--[[34]] { Name = 'MCB-WAIL', String = 'OISS_SSA_VEHAUD_SAHP_NEW_SIREN_ADAM', Ref = 'OISS_SSA_VEHAUD_SAHP_NEW_SOUNDSET'}, +--[[35]] { Name = 'MCB-YELP', String = 'OISS_SSA_VEHAUD_SAHP_NEW_SIREN_BOY', Ref = 'OISS_SSA_VEHAUD_SAHP_NEW_SOUNDSET'}, +--[[36]] { Name = 'MCB-HYPER-YELP', String = 'OISS_SSA_VEHAUD_SAHP_NEW_SIREN_CHARLES', Ref = 'OISS_SSA_VEHAUD_SAHP_NEW_SOUNDSET'}, +--[[37]] { Name = 'MCB-SWEEP3', String = 'OISS_SSA_VEHAUD_SAHP_NEW_SIREN_DAVID', Ref = 'OISS_SSA_VEHAUD_SAHP_NEW_SOUNDSET'}, +--[[38]] { Name = 'MCB-HYPERLO', String = 'OISS_SSA_VEHAUD_SAHP_NEW_SIREN_EDWARD', Ref = 'OISS_SSA_VEHAUD_SAHP_NEW_SOUNDSET', Option = 3}, +--[[39]] { Name = 'CGOLD-HORN', String = 'OISS_SSA_VEHAUD_FIB_NEW_HORN', Ref = 'OISS_SSA_VEHAUD_FIB_NEW_SOUNDSET'}, +--[[40]] { Name = 'CGOLD-WAIL', String = 'OISS_SSA_VEHAUD_FIB_NEW_SIREN_ADAM', Ref = 'OISS_SSA_VEHAUD_FIB_NEW_SOUNDSET'}, +--[[41]] { Name = 'CGOLD-YELP', String = 'OISS_SSA_VEHAUD_FIB_NEW_SIREN_BOY', Ref = 'OISS_SSA_VEHAUD_FIB_NEW_SOUNDSET'}, +--[[42]] { Name = 'CGOLD-PRIORITY', String = 'OISS_SSA_VEHAUD_FIB_NEW_SIREN_CHARLES', Ref = 'OISS_SSA_VEHAUD_FIB_NEW_SOUNDSET'}, +--[[43]] { Name = 'CGOLD-SWEEP', String = 'OISS_SSA_VEHAUD_FIB_NEW_SIREN_DAVID', Ref = 'OISS_SSA_VEHAUD_FIB_NEW_SOUNDSET'}, +--[[44]] { Name = 'CGOLD-SWEEP3', String = 'OISS_SSA_VEHAUD_FIB_NEW_SIREN_EDWARD', Ref = 'OISS_SSA_VEHAUD_FIB_NEW_SOUNDSET'}, +--[[45]] { Name = 'FIRE HORN', String = 'OISS_SSA_VEHAUD_LSFD_NEW_HORN', Ref = 'OISS_SSA_VEHAUD_LSFD_NEW_SOUNDSET'}, +--[[46]] { Name = 'POWERCALL', String = 'OISS_SSA_VEHAUD_LSFD_NEW_SIREN_ADAM', Ref = 'OISS_SSA_VEHAUD_LSFD_NEW_SOUNDSET'}, +--[[47]] { Name = 'Q-COAST', String = 'OISS_SSA_VEHAUD_LSFD_NEW_SIREN_BOY', Ref = 'OISS_SSA_VEHAUD_LSFD_NEW_SOUNDSET'}, +--[[48]] { Name = 'Q-HIGH', String = 'OISS_SSA_VEHAUD_LSFD_NEW_SIREN_CHARLES', Ref = 'OISS_SSA_VEHAUD_LSFD_NEW_SOUNDSET'}, +--[[49]] { Name = 'Q-MID', String = 'OISS_SSA_VEHAUD_BCFD_NEW_SIREN_DAVID', Ref = 'OISS_SSA_VEHAUD_BCFD_NEW_SOUNDSET'}, +--[[50]] { Name = 'Q-MID2', String = 'OISS_SSA_VEHAUD_BCFD_NEW_SIREN_EDWARD', Ref = 'OISS_SSA_VEHAUD_BCFD_NEW_SOUNDSET'}, +--[[51]] { Name = 'LAPD-HORN', String = 'OISS_SSA_VEHAUD_LSSD_OLD_HORN', Ref = 'OISS_SSA_VEHAUD_LSSD_OLD_SOUNDSET'}, +--[[52]] { Name = 'LAPD-WAIL', String = 'OISS_SSA_VEHAUD_LSSD_OLD_SIREN_BOY', Ref = 'OISS_SSA_VEHAUD_LSSD_OLD_SOUNDSET'}, +--[[53]] { Name = 'LAPD-YELP', String = 'OISS_SSA_VEHAUD_LSSD_OLD_SIREN_ADAM', Ref = 'OISS_SSA_VEHAUD_LSSD_OLD_SOUNDSET'}, +--[[54]] { Name = "Old SAHP HORN", String = "OISS_SSA_VEHAUD_SAHP_OLD_HORN", Ref = "OISS_SSA_VEHAUD_SAHP_OLD_SOUNDSET"}, +--[[55]] { Name = "Old SAHP ADAM", String = "OISS_SSA_VEHAUD_SAHP_OLD_SIREN_ADAM", Ref = "OISS_SSA_VEHAUD_SAHP_OLD_SOUNDSET"}, +--[[56]] { Name = "Old SAHP BOY", String = "OISS_SSA_VEHAUD_SAHP_OLD_SIREN_BOY", Ref = "OISS_SSA_VEHAUD_SAHP_OLD_SOUNDSET"}, +--[[57]] { Name = "Old SAHP CHARLES", String = "OISS_SSA_VEHAUD_SAHP_OLD_SIREN_CHARLES", Ref = "OISS_SSA_VEHAUD_SAHP_OLD_SOUNDSET"}, +--[[58]] { Name = "Old SAHP DAVID", String = "OISS_SSA_VEHAUD_SAHP_OLD_SIREN_DAVID", Ref = "OISS_SSA_VEHAUD_SAHP_OLD_SOUNDSET"}, +--[[59]] { Name = "Old SAHP EDWARD", String = "OISS_SSA_VEHAUD_SAHP_OLD_SIREN_EDWARD", Ref = "OISS_SSA_VEHAUD_SAHP_OLD_SOUNDSET"}, +--[[60]] { Name = "Old LSFD HORN", String = "OISS_SSA_VEHAUD_LSFD_OLD_HORN", Ref = "OISS_SSA_VEHAUD_LSFD_OLD_SOUNDSET"}, +--[[61]] { Name = "Old LSFD ADAM", String = "OISS_SSA_VEHAUD_LSFD_OLD_SIREN_ADAM", Ref = "OISS_SSA_VEHAUD_LSFD_OLD_SOUNDSET"}, +--[[62]] { Name = "Old LSFD BOY", String = "OISS_SSA_VEHAUD_LSFD_OLD_SIREN_BOY", Ref = "OISS_SSA_VEHAUD_LSFD_OLD_SOUNDSET"}, +--[[63]] { Name = "Old LSFD CHARLES", String = "OISS_SSA_VEHAUD_LSFD_OLD_SIREN_CHARLES", Ref = "OISS_SSA_VEHAUD_LSFD_OLD_SOUNDSET"}, +--[[64]] { Name = "Old LSFD DAVID", String = "OISS_SSA_VEHAUD_LSFD_OLD_SIREN_DAVID", Ref = "OISS_SSA_VEHAUD_LSFD_OLD_SOUNDSET"}, +--[[65]] { Name = "Old LSFD EDWARD", String = "OISS_SSA_VEHAUD_LSFD_OLD_SIREN_EDWARD", Ref = "OISS_SSA_VEHAUD_LSFD_OLD_SOUNDSET"}, +--[[66]] { Name = "CHPOLD-HORN", String = "OISS_SSA_VEHAUD_RHPD_OLD_HORN", Ref = "OISS_SSA_VEHAUD_RHPD_OLD_SOUNDSET"}, +--[[67]] { Name = "CHPOLD-ADAM", String = "OISS_SSA_VEHAUD_RHPD_OLD_SIREN_ADAM", Ref = "OISS_SSA_VEHAUD_RHPD_OLD_SOUNDSET"}, +--[[68]] { Name = "CHPOLD-BOY", String = "OISS_SSA_VEHAUD_RHPD_OLD_SIREN_BOY", Ref = "OISS_SSA_VEHAUD_RHPD_OLD_SOUNDSET"}, + + + + + +} + +--ASSIGN SIRENS TO VEHICLES +SIREN_ASSIGNMENTS = { + --[''] = { 21, 22, 23, 24, 25, 25 }, = {tones}, + ['DEFAULT'] = { 21, 22, 23 }, + ['FIRETRUK'] = { 21, 22, 23, 24, 25, 25 }, + ['AMBULAN'] = { 21, 22, 23, 24, 25, 25 }, + ['LGUARD'] = { 21, 22, 23, 24, 25, 25 }, + ['20ramambo'] = { 45, 61, 62, 63, 48}, + ['battalion'] = { 45, 61, 62, 63, 48}, + ['engine'] = { 45, 61, 62, 63, 48}, + ['rambulance'] = { 45, 61, 62, 63, 48}, + ['lafdengine'] = { 45, 61, 62, 63, 48}, + ['lafdrambulance'] = { 45, 61, 62, 63, 48}, + ['24ramambo'] = { 45, 16, 40, 38, 48, 31 }, + ['e350vanb'] = { 45, 16, 40, 38, 48, 31 }, + ['e450ambo'] = { 45, 16 ,40, 38, 48, 31 }, + ['ltundra'] = { 45, 16, 40, 38, 48, 31 }, + ['11firevic'] = { 33, 16, 40, 38, 48, 31 }, + ['16fexp'] = { 33, 16, 40, 38, 48, 31 }, + ['23fdems18suv'] = { 33, 61, 62, 63, 48}, + ['23fdems18suvsl'] = { 33, 16, 40, 38, 48, 31 }, + ['23fdems21suv'] = { 33, 16, 40, 38, 48, 31 }, + ['23fdems21suvsl'] = { 33, 16 ,40, 38, 48, 31 }, + ['2022heavycommandfd'] = { 45, 16,40, 38, 48, 31 }, + ['ALSrescue1'] = { 45, 16,40, 38, 48, 31 }, + ['amrvan'] = { 45, 16,40, 38, 48, 31 }, + ['chargfire'] = { 45, 16,40, 38, 48, 31 }, + ['f150batt'] = { 45, 16,40, 38, 48, 31 }, + ['f250ambo'] = { 45, 61, 62, 63, 48}, + ['fd14tahoe'] = { 45, 16,40, 38, 48, 31 }, + ['fd20exp'] = { 33, 16,40, 38, 48, 31 }, + ['medic22'] = { 45, 16,40, 38, 48, 31 }, + ['medic1a'] = { 45, 16,40, 38, 48, 31 }, + ['medic1b'] = { 45, 16,40, 38, 48, 31 }, + ['ram20pov'] = { 45, 16,40, 38, 48, 31 }, + ['safr_fleet'] = { 45, 16,40, 38, 48, 31 }, + ['walkinarrow'] = { 45, 16,40, 38, 48, 31 }, + ['engine6a'] = { 45, 48, 13, 50, 47, 46 }, + ['engine6d'] = { 45, 48, 13, 50, 47, 46 }, + ['roseeng'] = { 45, 48, 13, 50, 47, 46 }, + ['rosemidtower'] = { 45, 48, 13, 50, 47, 46 }, + ['ladder6a'] = { 45, 48, 13, 50, 47, 46 }, + ['fhauler'] = { 45, 48, 13, 50, 47, 46 }, + ['fireboat'] = { 45, 48, 13, 50, 47, 46 }, + ['fireburb'] = { 45, 48, 13, 50, 47, 46 }, + ['ford1utility1'] = { 45, 48, 13, 50, 47, 46 }, + ['ford2utility2'] = { 45, 48, 13, 50, 47, 46 }, + ['panther'] = { 45, 48, 13, 50, 47, 46 }, + ['ramfire2'] = { 45, 48, 13, 50, 47, 46 }, + ['silvfire'] = { 45, 48, 13, 50, 47, 46 }, + ['t3engine1'] = { 45, 48, 13, 50, 47, 46 }, + ['LACoFDDurango'] = { 33, 16,40, 38, 48, 31 }, + ['rescue6'] = { 45, 48, 13, 50, 47, 46 }, + ['rescue6a'] = { 45, 48, 13, 50, 47, 46 }, + ['rescue9e'] = { 45, 48, 13, 50, 47, 46 }, + ['tender6'] = { 45, 48, 13, 50, 47, 46 }, + ['tender9b'] = { 45, 48, 13, 50, 47, 46 }, + ['tower6'] = { 45, 48, 13, 50, 47, 46 }, + ['20Maxfdramsquad'] = { 45, 48, 13, 50, 47, 46 }, + ['23sierrafire'] = { 45, 48, 13, 50, 47, 46 }, + ['24rampumper'] = { 45, 48, 13, 50, 47, 46 }, + ['f550super6'] = { 45, 48, 13, 50, 47, 46 }, + ['ftanker'] = { 45, 48, 13, 50, 47, 46 }, + ['velocity'] = { 45, 48, 13, 50, 47, 46 }, + ['23smallboatfd'] = { 45, 48, 13, 50, 47, 46 }, + ['brush'] = { 45, 48, 13, 50, 47, 46 }, + ['brushram'] = { 45, 48, 13, 50, 47, 46 }, + ['bulldog'] = { 45, 48, 13, 50, 47, 46 }, + ['enforcer'] = { 45, 48, 13, 50, 47, 46 }, + ['EnforcerEng'] = { 45, 48, 13, 50, 47, 46 }, + ['enforcerf'] = { 45, 48, 13, 50, 47, 46 }, + ['enforcerta'] = { 45, 48, 13, 50, 47, 46 }, + ['enladder'] = { 45, 48, 13, 50, 47, 46 }, + ['fdgator'] = { 33, 48, 13, 50, 47, 46 }, + ['Ferrara'] = { 45, 48, 13, 50, 47, 46 }, + ['firef350'] = { 45, 48, 13, 50, 47, 46 }, + ['foam1'] = { 45, 48, 13, 50, 47, 46 }, + ['mmladder'] = { 45, 48, 13, 50, 47, 46 }, + ['prescue'] = { 45, 48, 13, 50, 47, 46 }, + ['rescue1'] = { 45, 48, 13, 50, 47, 46 }, + ['walkin'] = { 45, 48, 13, 50, 47, 46 }, + ['fireboat'] = { 45, 48, 13, 50, 47, 46 }, + ['lafdengine'] = { 45, 48, 13, 50, 47, 46 }, + ['lacod6'] = { 45, 48, 13, 46, 47, 49 }, + ['lacofdbat'] = { 45, 48, 13, 46, 47, 49 }, + ['lacofdbug'] = { 45, 48, 13, 46, 47, 49 }, + ['lacofddztrk'] = { 45, 48, 13, 46, 47, 49 }, + ['lacofdeng'] = { 45, 48, 13, 46, 47, 49 }, + ['lacofdfoam'] = { 45, 48, 13, 46, 47, 49 }, + ['lacofdpat'] = { 45, 48, 13, 46, 47, 49 }, + ['lacofdrs'] = { 45, 48, 13, 46, 47, 49 }, + ['lacofdsup'] = { 45, 48, 13, 46, 47, 49 }, + ['lacofdt3'] = { 45, 48, 13, 46, 47, 49 }, + ['lacofdtrlr'] = { 45, 48, 13, 46, 47, 49 }, + ['lacofdusartrk'] = { 45, 48, 13, 46, 47, 49 }, + ['lacofdusartrlr'] = { 45, 48, 13, 46, 47, 49 }, + ['lacofdutil'] = { 45, 48, 13, 46, 47, 49 }, + ['mmech'] = { 45, 48, 13, 46, 47, 49 }, + ['petewrecker'] = { 45, 48, 13, 46, 47, 49 }, + ['lafdtiller'] = { 45, 61, 62, 63, 48}, + ['lafdcab'] = { 45, 61, 62, 63, 48}, + ['lafdengine'] = { 45, 61, 62, 63, 48}, + ['21fireladder'] = { 45, 61, 62, 63, 48 }, + ['16ramcsquad'] = { 45, 48, 13, 46, 47, 49 }, + ['2021FDPack'] = { 45, 48, 13, 46, 47, 49 }, + ['20Maxfdramsquad'] = { 45, 48, 13, 46, 47, 49 }, + ['20ramcsquad'] = { 45, 48, 13, 46, 47, 49 }, + ['f550csquad'] = { 45, 48, 13, 46, 47, 49 }, + ['x3bearcat2'] = { 45, 48, 2, 28, 31, 29 }, + ['x3bearcat'] = { 45, 48, 13, 46, 47, 49 }, + ['lafdtahoe'] = { 45, 61, 62, 63, 48}, + ['firetruk13'] = { 45, 48, 13, 46, 47, 49, 61, 62, 63}, + ['hazf350tec'] = { 45, 48, 13, 46, 47, 49 }, + ['redf350brush21'] = { 45, 48, 13, 46, 47, 49 }, + ['lasd1997'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd1998'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd1999'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd2000'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd2001'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd2002'] = { 21, 22, 23, 24, 25, 25 }, + ['16expmet'] = { 21, 22, 23, 24, 25, 25 }, + ['lapdurango'] = { 51, 52, 53 }, + ['lasdurango'] = { 21, 22, 23, 24, 25, 25 }, + ['13lasdfpiu'] = { 21, 22, 23, 24, 25, 25 }, + ['13lasdfpiu2'] = { 21, 22, 23, 24, 25, 25 }, + ['13lasdfpiua'] = { 21, 22, 23, 24, 25, 25 }, + ['13lasdfpiuseb'] = { 21, 22, 23, 24, 25, 25 }, + ['dualpurpose1'] = { 21, 22, 23, 24, 25, 25 }, + ['dualpurpose3'] = { 21, 22, 23, 24, 25, 25 }, + ['hybridfpis'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd08'] = { 21, 22, 23, 24, 25, 25 }, + ['lacpvic'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd13fpiuv'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd14charger'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd14chargertd'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd16fpiu'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd16fpiu2'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd16fpiusecsd'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd16fpiutraffic'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd16fpiutraffic2'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd20chrgra'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd20sl'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd20unm1'] = { 21, 22, 23, 24, 25, 25 }, + ['lapdalpr20'] = { 21, 22, 23, 24, 25, 25 }, + ['lapdfpis'] = { 21, 22, 23, 24, 25, 25 }, + ['lapdfpis2'] = { 21, 22, 23, 24, 25, 25 }, + ['lapdfpiua'] = { 21, 22, 23, 24, 25, 25 }, + ['dualpurpose2'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd05cvpi'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd06cvpi'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd06cvpicarson'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd06cvpisd7100'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd06m'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd06u'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd08cvpi'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd08cvpilomita'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd08cvpitransit'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd15tahoe'] = { 21, 22, 23, 24, 25 }, + ['lasd15tahoeb'] = { 21, 22, 23, 24, 25 }, + ['lasd15k9'] = { 21, 22, 23, 24, 25 }, + ['lasd15k9b'] = { 21, 22, 23, 24, 25 }, + ['lasd20tahoe'] = { 21, 22, 23, 24, 25 }, + ['lasd20tfs'] = { 21, 22, 23, 24, 25 }, + ['lasd20k9'] = { 21, 22, 23, 24, 25 }, + ['lasd23tahoe'] = { 21, 22, 23, 24, 25 }, + ['lasd22tunm'] = { 21, 22, 23, 24, 25 }, + ['lasd23k9t'] = { 21, 22, 23, 24, 25 }, + ['lasd16asap'] = { 21, 22, 23, 24, 25 }, + ['lasd16asapb'] = { 21, 22, 23, 24, 25 }, + ['lasd16asapc'] = { 21, 22, 23, 24, 25 }, + ['lasd16asapd'] = { 21, 22, 23, 24, 25 }, + ['lasd16fpiu'] = { 21, 22, 23, 24, 25 }, + ['lasd16fpiub'] = { 21, 22, 23, 24, 25 }, + ['lasd16rfr'] = { 21, 22, 23, 24, 25 }, + ['lasd16rfrb'] = { 21, 22, 23, 24, 25 }, + ['lasd13fasap'] = { 21, 22, 23, 24, 25 }, + ['lasd13fpiu1'] = { 21, 22, 23, 24, 25 }, + ['lasd13fpiu2'] = { 21, 22, 23, 24, 25 }, + ['lasd13fpiu3'] = { 21, 22, 23, 24, 25 }, + ['lasd13fpiu4'] = { 21, 22, 23, 24, 25 }, + ['lasd13fpiu5'] = { 21, 22, 23, 24, 25 }, + ['lasd13fsfpiu'] = { 21, 22, 23, 24, 25 }, + ['asd13funm'] = { 21, 22, 23, 24, 25 }, + ['lasd13funm2'] = { 21, 22, 23, 24, 25 }, + ['lasd16chrgr'] = { 21, 22, 23, 24, 25 }, + ['lasd13funm3'] = { 21, 22, 23, 24, 25 }, + ['lasd13funm4'] = { 21, 22, 23, 24, 25 }, + ['lasd18chrg'] = { 21, 22, 23, 24, 25 }, + ['lacpvic'] = { 21, 22, 23, 24, 25 }, + ['lasd06m'] = { 21, 22, 23, 24, 25 }, + ['lasd06u'] = { 21, 22, 23, 24, 25 }, + ['lasdcrownvic'] = { 21, 22, 23, 24, 25 }, + ['lasdlithium'] = { 21, 22, 23, 24, 25 }, + ['lasdparamount'] = { 21, 22, 23, 24, 25 }, + ['lasdsd7100'] = { 21, 22, 23, 24, 25 }, + ['lasdvicslicktop'] = { 21, 22, 23, 24, 25 }, + ['lasd05cvpi'] = { 21, 22, 23, 24, 25 }, + ['lasd06cvpi'] = { 21, 22, 23, 24, 25 }, + ['lasd06cvpicarson'] = { 21, 22, 23, 24, 25 }, + ['lasd06cvpisd7100'] = { 21, 22, 23, 24, 25 }, + ['lasd08cvpi'] = { 21, 22, 23, 24, 25 }, + ['lasd08cvpilomita'] = { 21, 22, 23, 24, 25 }, + ['lasd08cvpitransit'] = { 21, 22, 23, 24, 25 }, + ['lasd08tahoe'] = { 21, 22, 23, 24, 25 }, + ['lasd08tahoe2'] = { 21, 22, 23, 24, 25 }, + ['lasd08tahoe3'] = { 21, 22, 23, 24, 25 }, + ['lasd14tahoe'] = { 21, 22, 23, 24, 25 }, + ['lasd15k9'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd15tahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd15tunm'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16asap'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd20fs'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd20k9'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd20tunm'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdchrg14'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdcrownvic'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdlithium'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdparamount'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdsd7100'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdvicslicktop'] = { 21, 22, 23, 24, 25, 25 }, + ['metrocharger'] = { 21, 22, 23, 24, 25, 25 }, + ['11lapdvic'] = { 21, 22, 23, 24, 25, 25 }, + ['11lapdvic2'] = { 21, 22, 23, 24, 25, 25 }, + ['13lapdexp'] = { 21, 22, 23, 24, 25, 25 }, + ['13lapdfpis'] = { 21, 22, 23, 24, 25, 25 }, + ['13lapdfpis2'] = { 21, 22, 23, 24, 25, 25 }, + ['14lapdchg'] = { 21, 22, 23, 24, 25, 25 }, + ['16lapdexp'] = { 21, 22, 23, 24, 25, 25 }, + ['16lapdexpk9'] = { 21, 22, 23, 24, 25, 25 }, + ['20lapdexp'] = { 21, 22, 23, 24, 25, 25 }, + ['20lapdexp2'] = { 21, 22, 23, 24, 25, 25 }, + ['20lapdexp3'] = { 21, 22, 23, 24, 25, 25 }, + ['20lapdexpk9'] = { 21, 22, 23, 24, 25, 25 }, + ['SHOP00000'] = { 21, 22, 23, 24, 25, 25 }, + ['SHOP80693'] = { 21, 22, 23, 24, 25, 25 }, + ['SHOP81365'] = { 21, 22, 23, 24, 25, 25 }, + ['SHOP81622'] = { 21, 22, 23, 24, 25, 25 }, + ['SHOP81906'] = { 21, 22, 23, 24, 25, 25 }, + ['SHOP83039'] = { 21, 22, 23, 24, 25, 25 }, + ['SHOP89471'] = { 21, 22, 23, 24, 25, 25 }, + ['SHOPFPIS'] = { 21, 22, 23, 24, 25, 25 }, + ['lapdcvpialpr'] = { 21, 22, 23, 24, 25, 25 }, + ['lapdcvpithermal'] = { 21, 22, 23, 24, 25, 25 }, + ['08hybridcvpi1'] = { 21, 22, 23, 24, 25, 25 }, + ['08hybridcvpi2'] = { 21, 22, 23, 24, 25, 25 }, + ['08lapdcvpi1'] = { 21, 22, 23, 24, 25, 25 }, + ['08lapdcvpi2'] = { 21, 22, 23, 24, 25, 25 }, + ['08lapdcvpighost'] = { 21, 22, 23, 24, 25, 25 }, + ['08lapdcvpiharbor'] = { 21, 22, 23, 24, 25, 25 }, + ['08lapdcvpisecsd'] = { 21, 22, 23, 24, 25, 25 }, + ['08lapdsap'] = { 21, 22, 23, 24, 25, 25 }, + ['2005LAPDCVPI_Hybrid1'] = { 21, 22, 23, 24, 25, 25 }, + ['2005LAPDCVPI_Hybrid2'] = { 21, 22, 23, 24, 25, 25 }, + ['2005LAPDCVPI_HybridH'] = { 21, 22, 23, 24, 25, 25 }, + ['2008LAPDCVPI_77th1'] = { 21, 22, 23, 24, 25, 25 }, + ['2008LAPDCVPI_77th2'] = { 21, 22, 23, 24, 25, 25 }, + ['2008LAPDCVPI_Hardtop1'] = { 21, 22, 23, 24, 25, 25 }, + ['2008LAPDCVPI_Hardtop2'] = { 21, 22, 23, 24, 25, 25 }, + ['2008LAPDCVPI_Hybrid1'] = { 21, 22, 23, 24, 25, 25 }, + ['2008LAPDCVPI_Hybrid2'] = { 21, 22, 23, 24, 25, 25 }, + ['2008LAPDCVPI_HybridT'] = { 21, 22, 23, 24, 25, 25 }, + ['2008LAPDCVPI_Traffic1'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd16fpiu'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd16fpiu2'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd16fpiusecsd'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd16fpiutraffic'] = { 21, 22, 23, 24, 25, 25 }, + ['metro16fpiu'] = { 21, 22, 23, 24, 25, 25 }, + ['metro16fpiu2'] = { 21, 22, 23, 24, 25, 25 }, + ['metro16fpiu3'] = { 21, 22, 23, 24, 25, 25 }, + ['18challengerbw'] = { 21, 22, 23, 24, 25, 25 }, + ['21mach1stang'] = { 21, 22, 23, 24, 25, 25 }, + ['19mustgt'] = { 21, 22, 23, 24, 25, 25 }, + ['21tacouc'] = { 21, 22, 23, 24, 25, 25 }, + ['21f150'] = { 21, 22, 23, 24, 25, 25 }, + ['22f150rb'] = { 21, 22, 23, 24, 25, 25 }, + ['23f150pr'] = { 21, 22, 23, 24, 25, 25 }, + ['23f150prbb'] = { 21, 22, 23, 24, 25, 25 }, + ['23f150st'] = { 21, 22, 23, 24, 25, 25 }, + ['23gmcleo'] = { 21, 22, 23, 24, 25, 25 }, + ['23gmcleoslick'] = { 21, 22, 23, 24, 25, 25 }, + ['23hoe'] = { 21, 22, 23, 24, 25, 25 }, + ['23ram6'] = { 21, 22, 23, 24, 25, 25 }, + ['24tactrd'] = { 21, 22, 23, 24, 25, 25 }, + ['2019GMCSlick'] = { 21, 22, 23, 24, 25, 25 }, + ['hpsrtcat18'] = { 21, 22, 23, 24, 25, 25 }, + ['Maxpursuit'] = { 21, 22, 23, 24, 25, 25 }, + ['max-stang21'] = { 21, 22, 23, 24, 25, 25 }, + ['Polmrambb23'] = { 21, 22, 23, 24, 25, 25 }, + ['mxxraprb'] = { 21, 22, 23, 24, 25, 25 }, + ['whelen22sierra'] = { 21, 22, 23, 24, 25, 25 }, + ['max2021f150'] = { 21, 22, 23, 24, 25, 25 }, + ['maxdrkhorse'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdcharger'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd1997'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd1998'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd1999'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd2000'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd2001'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd2002'] = { 21, 22, 23, 24, 25, 25 }, + ['16expmet'] = { 21, 22, 23, 24, 25, 25 }, + ['lapdurango'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdurango'] = { 21, 22, 23, 24, 25, 25 }, + ['13lasdfpiu'] = { 21, 22, 23, 24, 25, 25 }, + ['13lasdfpiu2'] = { 21, 22, 23, 24, 25, 25 }, + ['13lasdfpiua'] = { 21, 22, 23, 24, 25, 25 }, + ['13lasdfpiuseb'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdchg'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdexp'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdexp2'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdfpiu'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdfpiu2'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdfpiu3'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdfpiu4'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdtahoe2'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdvic'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdvic2'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd08tahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd08tahoe2'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd14tahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdchrg14'] = { 21, 22, 23, 24, 25, 25 }, + ['LASDCVPI2'] = { 21, 22, 23, 24, 25, 25 }, + ['22tahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['18challengerbw'] = { 16, 17, 18, 19, 20, 29 }, + ['21mach1stang'] = { 16, 17, 18, 19, 20, 29 }, + ['19mustgt'] = { 16, 17, 18, 19, 20, 29 }, + ['21tacouc'] = { 21, 22, 23, 24, 25, 25 }, + ['21f150'] = { 21, 22, 23, 24, 25, 25 }, + ['22f150rb'] = { 21, 22, 23, 24, 25, 25 }, + ['23f150pr'] = { 21, 22, 23, 24, 25, 25 }, + ['23f150prbb'] = { 21, 22, 23, 24, 25, 25 }, + ['23f150st'] = { 21, 22, 23, 24, 25, 25 }, + ['23gmcleo'] = { 21, 22, 23, 24, 25, 25 }, + ['23gmcleoslick'] = { 21, 22, 23, 24, 25, 25 }, + ['23hoe'] = { 21, 22, 23, 24, 25, 25 }, + ['23ram6'] = { 21, 22, 23, 24, 25, 25 }, + ['24tactrd'] = { 21, 22, 23, 24, 25, 25 }, + ['2019GMCSlick'] = { 21, 22, 23, 24, 25, 25 }, + ['hpsrtcat18'] = { 21, 22, 23, 24, 25, 25 }, + ['Maxpursuit'] = { 21, 22, 23, 24, 25, 25 }, + ['max-stang21'] = { 21, 22, 23, 24, 25, 25 }, + ['Polmrambb23'] = { 21, 22, 23, 24, 25, 25 }, + ['mxxraprb'] = { 21, 22, 23, 24, 25, 25 }, + ['whelen22sierra'] = { 21, 22, 23, 24, 25, 25 }, + ['max2021f150'] = { 21, 22, 23, 24, 25, 25 }, + ['maxdrkhorse'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd18taurus'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd06tahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16ram'] = { 15, 16, 29, 31, 32, 18 }, + ['lax20fpiu'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdcharger'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdchg'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdexp'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdexp2'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdfpiu'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdfpiu2'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdfpiu3'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdfpiu4'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdtahoe2'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdvic'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdvic2'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd08tahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd08tahoe2'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd14tahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdchrg14'] = { 21, 22, 23, 24, 25, 25 }, + ['LASDCVPI2'] = { 21, 22, 23, 24, 25, 25 }, + ['22tahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['SMPDF150'] = { 21, 22, 23, 24, 25, 25 }, + ['CHP18D'] = { 54, 55, 56, 57 }, + ['chp19k9tahoe'] = { 54, 55, 56, 57 }, + ['chp24durango'] = { 54, 55, 56, 57 }, + ['chp20fpiu'] = { 54, 55, 56, 57 }, + ['chp20fpiugr'] = { 54, 55, 56, 57 }, + ['chpsilv24'] = { 54, 55, 56, 57 }, + ['chptahoe24'] = { 54, 55, 56, 57 }, + ['chpumtahoe'] = { 54, 55, 56, 57 }, + ['sahp18tahoe'] = { 54, 55, 56, 57 }, + ['chp1'] = { 54, 55, 56, 57 }, + ['chp23durangop'] = { 54, 55, 56, 57 }, + ['chp2'] = { 54, 55, 56, 57 }, + ['chp3'] = { 54, 55, 56, 57 }, + ['chp4'] = { 54, 55, 56, 57 }, + ['chp5'] = { 54, 55, 56, 57 }, + ['chp6'] = { 54, 55, 56, 57 }, + ['chp11cvpi'] = { 54, 55, 56, 57 }, + ['chp11cvpiS'] = { 54, 55, 56, 57 }, + ['chp13harley'] = { 54, 55, 56, 57 }, + ['chp16fpiu'] = { 54, 55, 56, 57 }, + ['chp18charger'] = { 54, 55, 56, 57 }, + ['chp20fpiuS'] = { 54, 55, 56, 57 }, + ['chp20tahoe'] = { 54, 55, 56, 57 }, + ['chp1200rt'] = { 54, 55, 56, 57 }, + ['hp11cvpi1'] = { 66, 67, 68 }, + ['hp11cvpi2'] = { 54, 55, 56, 57 }, + ['hp11cvpi3'] = { 54, 55, 56, 57 }, + ['hp11cvpi4'] = { 54, 55, 56, 57 }, + ['hp11cvpi5'] = { 54, 55, 56, 57 }, + ['hp11cvpi6'] = { 54, 55, 56, 57 }, + ['hp14fpiu1'] = { 54, 55, 56, 57 }, + ['hp14fpiu2'] = { 54, 55, 56, 57 }, + ['hp15fpiu1'] = { 54, 55, 56, 57 }, + ['hp15fpiu2'] = { 54, 55, 56, 57 }, + ['hp16fpiu1'] = { 54, 55, 56, 57 }, + ['hp16fpiu2'] = { 54, 55, 56, 57 }, + ['hp21charger1'] = { 54, 55, 56, 57 }, + ['hp21charger2'] = { 54, 55, 56, 57 }, + ['hp23charger1'] = { 54, 55, 56, 57 }, + ['hp23charger2'] = { 54, 55, 56, 57 }, + ['hp23charger3'] = { 54, 55, 56, 57 }, + ['hp23charger4'] = { 54, 55, 56, 57 }, + ['hp23charger5'] = { 54, 55, 56, 57 }, + ['hp23charger6'] = { 54, 55, 56, 57 }, + ['hp23charger7'] = { 54, 55, 56, 57 }, + ['chp1200'] = { 54, 55, 56, 57 }, + ['chpbearcat'] = { 54, 55, 56, 57 }, + ['chpchg'] = { 54, 55, 56, 57 }, + ['chpchg2'] = { 54, 55, 56, 57 }, + ['chpchg3'] = { 54, 55, 56, 57 }, + ['chpchg4'] = { 54, 55, 56, 57 }, + ['chpchg5'] = { 54, 55, 56, 57 }, + ['chpchg6'] = { 54, 55, 56, 57 }, + ['chpchg7'] = { 54, 55, 56, 57 }, + ['chpdurango'] = { 54, 55, 56, 57 }, + ['chpdurango2'] = { 54, 55, 56, 57 }, + ['chpexp'] = { 54, 55, 56, 57 }, + ['chpfpiu'] = { 54, 55, 56, 57 }, + ['chpfpiu2'] = { 54, 55, 56, 57 }, + ['chpfpiu3'] = { 54, 55, 56, 57 }, + ['chpfpiu4'] = { 54, 55, 56, 57 }, + ['chpfpiu5'] = { 54, 55, 56, 57 }, + ['chpfpiu6'] = { 54, 55, 56, 57 }, + ['chpfpiu7'] = { 54, 55, 56, 57 }, + ['chpfpiu8'] = { 54, 55, 56, 57 }, + ['chpfpiuk9'] = { 54, 55, 56, 57 }, + ['chpram'] = { 54, 55, 56, 57 }, + ['chpsilverado'] = { 54, 55, 56, 57 }, + ['chpsub'] = { 54, 55, 56, 57 }, + ['chptahoe'] = { 54, 55, 56, 57 }, + ['chptahoe2'] = { 54, 55, 56, 57 }, + ['chptahoe3'] = { 54, 55, 56, 57 }, + ['chptahoe4'] = { 54, 55, 56, 57 }, + ['chptahoe5'] = { 54, 55, 56, 57 }, + ['chptahoe6'] = { 54, 55, 56, 57 }, + ['chptahoe7'] = { 54, 55, 56, 57 }, + ['chptahoek9'] = { 54, 55, 56, 57 }, + ['chpvic'] = { 54, 55, 56, 57 }, + ['chpvic'] = { 54, 55, 56, 57 }, + ['chp11cvpi'] = { 54, 55, 56, 57 }, + ['chp15expedition'] = { 54, 55, 56, 57 }, + ['chp15f250'] = { 54, 55, 56, 57 }, + ['chp15fpiuk9'] = { 54, 55, 56, 57 }, + ['chp15fpiup'] = { 54, 55, 56, 57 }, + ['chp15fpius'] = { 54, 55, 56, 57 }, + ['chp16fpiu'] = { 54, 55, 56, 57 }, + ['chp16fpiup'] = { 54, 55, 56, 57 }, + ['chp15fpiup'] = { 54, 55, 56, 57 }, + ['chp15fpius'] = { 54, 55, 56, 57 }, + ['chp20tahoe'] = { 54, 55, 56, 57 }, + ['chp18tahoe'] = { 54, 55, 56, 57 }, + ['chp16ram'] = { 54, 55, 56, 57 }, + ['chp18charg'] = { 54, 55, 56, 57 }, + ['chp18chargst'] = { 54, 55, 56, 57 }, + ['chp18tahoe'] = { 54, 55, 56, 57 }, + ['chp20charg'] = { 54, 55, 56, 57 }, + ['chp20tahoe'] = { 54, 55, 56, 57 }, + ['chp211tahoe'] = { 54, 55, 56, 57 }, + ['chp23charg'] = { 54, 55, 56, 57 }, + ['chp23charggr'] = { 54, 55, 56, 57 }, + ['chp23charg'] = { 54, 55, 56, 57 }, + ['chp23chargp'] = { 54, 55, 56, 57 }, + ['chp23durango'] = { 54, 55, 56, 57 }, + ['chp23durangop'] = { 54, 55, 56, 57 }, + ['chpum15fpiu'] = { 54, 55, 56, 57 }, + ['chp20fpiup'] = { 54, 55, 56, 57 }, + ['chp20fpiu'] = { 54, 55, 56, 57 }, + ['chp20fpiugr'] = { 54, 55, 56, 57 }, + ['chp20fpiu'] = { 54, 55, 56, 57 }, + ['chp2'] = { 54, 55, 56, 57 }, + ['hp1'] = { 54, 55, 56, 57 }, + ['hp2'] = { 54, 55, 56, 57 }, + ['hp3'] = { 54, 55, 56, 57 }, + ['hp5'] = { 54, 55, 56, 57 }, + ['hp1st'] = { 54, 55, 56, 57 }, + ['hp3st'] = { 54, 55, 56, 57 }, + ['CHP9'] = { 54, 55, 56, 57 }, + ['CHP18D'] = { 54, 55, 56, 57 }, + ['maxcamaro19'] = { 54, 55, 56, 57 }, + ['zr1RB'] = { 54, 55, 56, 57 }, + ['fhp_20fpiu2'] = { 54, 16, 17, 18, 19, 20 }, + ['fhp_20fpiu2st'] = { 54, 16, 17, 18, 19, 20 }, + ['fhp_charger3'] = { 54, 16, 17, 18, 19, 20 }, + ['fhp_charger3bw'] = { 54, 16, 17, 18, 19, 20 }, + ['fhp_charger3st'] = { 54, 16, 17, 18, 19, 20 }, + ['fhp_charger3ta'] = { 54, 16, 17, 18, 19, 20 }, + ['fhp_charger3uc'] = { 54, 16, 17, 18, 19, 20 }, + ['fhp_durango'] = { 54, 16, 17, 18, 19, 20 }, + ['fhp_durangost'] = { 54, 16, 17, 18, 19, 20 }, + ['gt24non'] = { 54, 16, 17, 18, 19, 20 }, + ['lapd5'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd5b'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd10'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdoldtahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['PD23Suburban'] = { 21, 22, 23, 24, 25, 25 }, + ['ls14calpr'] = { 15, 28, 29, 30, 31, 32 }, + ['ls14chrgr'] = { 15, 28, 29, 30, 31, 32 }, + ['ls14tahoe'] = { 15, 28, 29, 30, 31, 32 }, + ['ls14talpr'] = { 15, 28, 29, 30, 31, 32 }, + ['ls16falpr'] = { 15, 28, 29, 30, 31, 32 }, + ['ls18calpr'] = { 15, 28, 29, 30, 31, 32 }, + ['ls18chrgr'] = { 15, 28, 29, 30, 31, 32 }, + ['ls20falpr'] = { 15, 28, 29, 30, 31, 32 }, + ['ls20tahoe'] = { 15, 28, 29, 30, 31, 32 }, + ['ls20talpr'] = { 15, 28, 29, 30, 31, 32 }, + ['maxcamaro19'] = { 54, 55, 56, 57 }, + ['Retro1'] = { 15, 16, 17, 18, 19, 20 }, + ['Retro2'] = { 15, 16, 17, 18, 19, 20 }, + ['retro3'] = { 15, 28, 29, 30, 31, 32 }, + ['retro4'] = { 15, 28, 29, 30, 31, 32 }, + ['rye20fpiu'] = { 15, 28, 29, 30, 31, 32 }, + ['rye20fpiurb'] = { 15, 28, 29, 30, 31, 32 }, + ['rye23tahoe'] = { 15, 28, 29, 30, 31, 32 }, + ['sdgcvpi'] = { 15, 28, 29, 30, 31, 32 }, + ['warden1'] = { 15, 28, 29, 30, 31, 32 }, + ['warden2'] = { 15, 28, 29, 30, 31, 32 }, + ['warden3'] = { 15, 28, 29, 30, 31, 32 }, + ['warden4'] = { 15, 28, 29, 30, 31, 32 }, + ['warden5'] = { 15, 28, 29, 30, 31, 32 }, + ['warden6'] = { 15, 28, 29, 30, 31, 32 }, + ['warden7'] = { 15, 28, 29, 30, 31, 32 }, + ['warden8'] = { 15, 28, 29, 30, 31, 32 }, + ['warden9'] = { 15, 28, 29, 30, 31, 32 }, + ['maxfedv'] = { 21, 22, 23, 24, 25, 25 }, + ['justice1'] = { 21, 22, 23, 24, 25, 25 }, + ['justice1canine'] = { 15, 28, 29, 30, 31, 32 }, + ['justice4'] = { 15, 28, 29, 30, 31, 32 }, + ['justice4canine'] = { 15, 28, 29, 30, 31, 32 }, + ['dsp19tahoe'] = { 15, 28, 29, 30, 31, 32 }, + ['231500rb'] = { 21, 22, 23, 24, 25, 25 }, + ['615'] = { 15, 28, 29, 30, 31, 32 }, + ['19Yukonrb'] = { 21, 22, 23, 24, 25, 25 }, + ['19yukonslick'] = { 21, 22, 23, 24, 25, 25 }, + ['20expk9rb'] = { 21, 22, 23, 24, 25, 25 }, + ['20fpiu_pd'] = { 21, 22, 23, 24, 25, 25 }, + ['22expedition'] = { 21, 22, 23, 24, 25, 25 }, + ['22jeepleo'] = { 21, 22, 23, 24, 25, 25 }, + ['18gtruckrb'] = { 21, 22, 23, 24, 25, 25 }, + ['14F250'] = { 21, 22, 23, 24, 25, 25 }, + ['20FDMTahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['20TAHOEPPV19'] = { 21, 22, 23, 24, 25, 25 }, + ['2022pshrb'] = { 21, 22, 23, 24, 25, 25 }, + ['dhssemi'] = { 21, 22, 23, 24, 25, 25 }, + ['fbicharger'] = { 21, 22, 23, 24, 25, 25 }, + ['GC21F250'] = { 21, 22, 23, 24, 25, 25 }, + ['maxdrkhorse'] = { 21, 22, 23, 24, 25, 25 }, + ['MAXr2bison'] = { 21, 22, 23, 24, 25, 25 }, + ['nforce24mustangS'] = { 21, 22, 23, 24, 25, 25 }, + ['nm_jeep'] = { 21, 22, 23, 24, 25, 25 }, + ['bhpdexp'] = { 15, 16, 17, 18, 19, 20 }, + ['bhpdtahoe'] = { 15, 16, 17, 18, 19, 20 }, + ['bhpdtahoek9'] = { 15, 16, 17, 18, 19, 20 }, + ['24mustanggt4d'] = { 21, 22, 23, 24, 25, 25 }, + ['speed1'] = { 21, 22, 23, 24, 25, 25 }, + ['schp16piu'] = { 15, 16, 17, 18, 19, 20 }, + ['pdstang'] = { 21, 22, 23, 24, 25, 25 }, + ['Zl116Camaro'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd06tahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16ram'] = { 21, 22, 23, 16, 17, 18, 19, 20 }, + ['lasd_airtwo'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd18taurus'] = { 21, 22, 23, 24, 25, 25 }, + ['seudemon'] = { 21, 22, 23, 24, 25, 25 }, + ['seumustang'] = { 21, 22, 23, 24, 25, 25 }, + ['pdstang'] = { 21, 22, 23, 24, 25, 25 }, + ['Zl116Camaro'] = { 21, 22, 23, 24, 25, 25 }, + ['rbst18charger'] = { 21, 22, 23, 24, 25, 25 }, + ['sof250'] = { 15, 28, 29, 30, 31, 32 }, + ['sof250slick'] = { 15, 28, 29, 30, 31, 32 }, + ['sof250k9'] = { 15, 28, 29, 30, 31, 32 }, + ['rye20fpiu'] = { 15, 28, 29, 30, 31, 32 }, + ['rye20fpiurb'] = { 15, 28, 29, 30, 31, 32 }, + ['rye23tahoe'] = { 15, 28, 29, 30, 31, 32 }, + ['ls14calpr'] = { 15, 16, 17, 18, 19, 20 }, + ['ls14chrgr'] = { 15, 16, 17, 18, 19, 20 }, + ['ls14tahoe'] = { 15, 16, 17, 18, 19, 20 }, + ['ls14talpr'] = { 15, 16, 17, 18, 19, 20 }, + ['ls16falpr'] = { 15, 16, 17, 18, 19, 20 }, + ['ls18calpr'] = { 15, 16, 17, 18, 19, 20 }, + ['ls18chrgr'] = { 15, 16, 17, 18, 19, 20 }, + ['ls20falpr'] = { 15, 16, 17, 18, 19, 20 }, + ['ls20tahoe'] = { 15, 16, 17, 18, 19, 20 }, + ['ls20talpr'] = { 15, 16, 17, 18, 19, 20 }, + ['SW8'] = { 21, 22, 23, 24, 25, 25 }, + ['SW3'] = { 21, 22, 23, 24, 25, 25 }, + ['SW2'] = { 21, 22, 23, 24, 25, 25 }, + ['SW1'] = { 21, 22, 23, 24, 25, 25 }, + ['GL_Mustang'] = { 21, 22, 23, 24, 25, 25 }, + ['24mustunmr1'] = { 21, 22, 23, 24, 25, 25 }, + ['rbst18charger'] = { 21, 22, 23, 24, 25, 25 }, + ['c321exptaxi'] = { 21, 22, 23, 24, 25, 25 }, + ['909_broncolib'] = { 21, 22, 23, 24, 25, 25 }, + ['909_21bronco'] = { 21, 22, 23, 24, 25, 25 }, + ['909_haul'] = { 21, 22, 23, 24, 25, 25 }, + ['20sierrarescue'] = { 21, 22, 23, 24, 25, 25 }, + ['14chgrlegacy'] = { 21, 22, 23, 24, 25, 25 }, + ['19explegacy'] = { 21, 22, 23, 24, 25, 25 }, + ['11viclegacy'] = { 21, 22, 23, 24, 25, 25 }, + ['19tundralegacy'] = { 21, 22, 23, 24, 25, 25 }, + ['18expdlegacy'] = { 21, 22, 23, 24, 25, 25 }, + ['18chgrlegacy'] = { 21, 22, 23, 24, 25, 25 }, + ['14tahoelegacy'] = { 21, 22, 23, 24, 25, 25 }, + ['909_broncolegacy'] = { 21, 22, 23, 24, 25, 25 }, + ['16lasdfpiu1'] = { 21, 22, 23, 24, 25, 25 }, + ['16lasdfpiu2'] = { 21, 22, 23, 24, 25, 25 }, + ['16lasdfpiuasap1'] = { 21, 22, 23, 24, 25, 25 }, + ['16lasdfpiuasap2'] = { 21, 22, 23, 24, 25, 25 }, + ['16lasdfpiuU'] = { 21, 22, 23, 24, 25, 25 }, + ['18lasdfpiu1'] = { 21, 22, 23, 24, 25, 25 }, + ['18lasdfpiu2'] = { 21, 22, 23, 24, 25, 25 }, + ['18lasdfpiuasap1'] = { 21, 22, 23, 24, 25, 25 }, + ['18lasdfpiuasap2'] = { 21, 22, 23, 24, 25, 25 }, + ['19lasdfpiu1'] = { 21, 22, 23, 24, 25, 25 }, + ['20fpiu'] = { 21, 22, 23, 24, 25, 25 } , + ['20fpiucoroner'] = { 21, 22, 23, 24, 25, 25 }, + ['20ramswr'] = { 21, 22, 23, 24, 25, 25 }, + ['701'] = { 21, 22, 23, 24, 25, 25 }, + ['2020MET'] = { 21, 22, 23, 24, 25, 25 }, + ['21132'] = { 21, 22, 23, 24, 25, 25 }, + ['83727'] = { 21, 22, 23, 24, 25, 25 }, + ['84361'] = { 21, 22, 23, 24, 25, 25 }, + ['85734'] = { 21, 22, 23, 24, 25, 25 }, + ['86385'] = { 21, 22, 23, 24, 25, 25 }, + ['86399'] = { 21, 22, 23, 24, 25, 25 }, + ['86486'] = { 21, 22, 23, 24, 25, 25 }, + ['87136'] = { 21, 22, 23, 24, 25, 25 }, + ['batram'] = { 21, 22, 23, 24, 25, 25 }, + ['bcfiretruk'] = { 21, 22, 23, 24, 25, 25 }, + ['bcsoslick'] = { 21, 22, 23, 24, 25, 25 }, + ['bcv03'] = { 21, 22, 23, 24, 25, 25 }, + ['centurion'] = { 21, 22, 23, 24, 25, 25 }, + ['centurionfib'] = { 21, 22, 23, 24, 25, 25 }, + ['centurionlspd'] = { 21, 22, 23, 24, 25, 25 }, + ['centurionlssd'] = { 21, 22, 23, 24, 25, 25 }, + ['coroner'] = { 21, 22, 23, 24, 25, 25 }, + ['coroner2'] = { 21, 22, 23, 24, 25, 25 }, + ['deanfleetengine4'] = { 21, 22, 23, 24, 25, 25 }, + ['dilettante2'] = { 21, 22, 23, 24, 25, 25 }, + ['enforcerengine'] = { 21, 22, 23, 24, 25, 25 }, + ['esdscout'] = { 21, 22, 23, 24, 25, 25 }, + ['esdyos'] = { 21, 22, 23, 24, 25, 25 }, + ['esdyos2'] = { 21, 22, 23, 24, 25, 25 }, + ['f150'] = { 21, 22, 23, 24, 25, 25 }, + ['fbi'] = { 21, 22, 23, 24, 25, 25 }, + ['fbi2'] = { 21, 22, 23, 24, 25, 25 }, + ['fbi3'] = { 21, 22, 23, 24, 25, 25 }, + ['fbi4'] = { 21, 22, 23, 24, 25, 25 }, + ['fdc150'] = { 21, 22, 23, 24, 25, 25 }, + ['firestonedurango'] = { 15, 16, 17, 18, 19, 20 }, + ['firestonepolice1'] = { 15, 16, 17, 18, 19, 20 }, + ['firestonepolice2'] = { 15, 16, 17, 18, 19, 20 }, + ['firestonepolice3'] = { 15, 16, 17, 18, 19, 20 }, + ['firestonepolice4'] = { 15, 16, 17, 18, 19, 20 }, + ['firestoneunmarked1'] = { 15, 16, 17, 18, 19, 20 }, + ['firestoneunmarked2'] = { 15, 16, 17, 18, 19, 20 }, + ['firetahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['fpiu'] = { 21, 22, 23, 24, 25, 25 }, + ['fpiu1'] = { 21, 22, 23, 24, 25, 25 }, + ['hwaycar'] = { 54, 55, 56, 57 }, + ['hwaycar2'] = { 21, 22, 23, 24, 25, 25 }, + ['hwaycar3'] = { 21, 22, 23, 24, 25, 25 }, + ['hwaycar4'] = { 21, 22, 23, 24, 25, 25 }, + ['hwaycar5'] = { 21, 22, 23, 24, 25, 25 }, + ['hwaycar6'] = { 21, 22, 23, 24, 25, 25 }, + ['hwaycar21'] = { 21, 22, 23, 24, 25, 25 }, + ['hwaycar22'] = { 21, 22, 23, 24, 25, 25 }, + ['hwaycar31'] = { 21, 22, 23, 24, 25, 25 }, + ['hwaycar41'] = { 21, 22, 23, 24, 25, 25 }, + ['hwaycar42'] = { 21, 22, 23, 24, 25, 25 }, + ['hybridfpis'] = { 21, 22, 23, 24, 25, 25 }, + ['lacpvic'] = { 21, 22, 23, 24, 25, 25 }, + ['lafd18tahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['lafd20tahoearson'] = { 21, 22, 23, 24, 25, 25 }, + ['lafd20tahoeumk'] = { 21, 22, 23, 24, 25, 25 }, + ['lafdarr'] = { 21, 22, 23, 24, 25, 25 }, + ['lafdbatt'] = { 21, 22, 23, 24, 25, 25 }, + ['lafdc'] = { 21, 22, 23, 24, 25, 25 }, + ['lafdcab'] = { 21, 22, 23, 24, 25, 25 }, + ['lafdcharger18'] = { 21, 22, 23, 24, 25, 25 }, + ['lafdkme'] = { 21, 22, 23, 24, 25, 25 }, + ['lafdtahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['lafdtems'] = { 21, 22, 23, 24, 25, 25 }, + ['lafdtiller'] = { 21, 22, 23, 24, 25, 25 }, + ['lafdxt6700'] = { 21, 22, 23, 24, 25, 25 }, + ['lafirechief'] = { 21, 22, 23, 24, 25, 25 }, + ['lafiretahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd6'] = { 51, 52, 53 }, + ['lapd13fmb'] = { 51, 52, 53 }, + ['lapd13fpiunew'] = { 51, 52, 53 }, + ['lapd13fpiusoe'] = { 51, 52, 53 }, + ['lapd13fpiuv'] = { 51, 52, 53 }, + ['lapd13funm'] = { 51, 52, 53 }, + ['lapd13funmb'] = { 51, 52, 53 }, + ['lapd13tahoe'] = { 51, 52, 53 }, + ['lapd13tfmb'] = { 51, 52, 53 }, + ['lapd13tfpiu'] = { 51, 52, 53 }, + ['lapd13vfpiu'] = { 51, 52, 53 }, + ['lapd14charger'] = { 51, 52, 53 }, + ['lapd13vfpiu'] = { 51, 52, 53 }, + ['lapd14chargertd'] = { 51, 52, 53 }, + ['lapd14chargertd'] = { 51, 52, 53 }, + ['lapd16fpiua'] = { 51, 52, 53 }, + ['lapd16fpiub'] = { 51, 52, 53 }, + ['lapd16fpiuburn'] = { 51, 52, 53 }, + ['lapd16fpiuc'] = { 51, 52, 53 }, + ['lapd16fpiuct'] = { 51, 52, 53 }, + ['lapd16fpiuhar'] = { 51, 52, 53 }, + ['lapd16fpiuhbk'] = { 51, 52, 53 }, + ['lapd16fpiunew'] = { 51, 52, 53 }, + ['lapd16fpiuoly'] = { 51, 52, 53 }, + ['lapd16fpiura'] = { 51, 52, 53 }, + ['lapd16fpiusoe'] = { 51, 52, 53 }, + ['lapd16sfpiua'] = { 51, 52, 53 }, + ['lapd16sfpiub'] = { 51, 52, 53 }, + ['lapd16sfpiuhar'] = { 51, 52, 53 }, + ['lapd16tfpiua'] = { 51, 52, 53 }, + ['lapd16tfpiub'] = { 51, 52, 53 }, + ['lapd16tfpiuc'] = { 51, 52, 53 }, + ['lapd16tfpiud'] = { 51, 52, 53 }, + ['05lapdvic'] = { 51, 52, 53 }, + ['11lapdvic'] = { 51, 52, 53 }, + ['11lapdvic2'] = { 51, 52, 53 }, + ['13lapdexp'] = { 51, 52, 53 }, + ['13lapdfpis'] = { 51, 52, 53 }, + ['13lapdfpis2'] = { 51, 52, 53 }, + ['14lapdchg'] = { 51, 52, 53 }, + ['14lapdchg2'] = { 51, 52, 53 }, + ['16lapdexp'] = { 51, 52, 53 }, + ['16lapdexp2'] = { 51, 52, 53 }, + ['16lapdexpk9'] = { 51, 52, 53 }, + ['17colorado'] = { 51, 52, 53 }, + ['20lapdexp'] = { 51, 52, 53 }, + ['20lapdexp2'] = { 51, 52, 53 }, + ['20lapdexp3'] = { 51, 52, 53 }, + ['20lapdexpk9'] = { 51, 52, 53 }, + ['25lapdexp'] = { 51, 52, 53 }, + ['25lapdexp2'] = { 51, 52, 53 }, + ['25lapdexpk9'] = { 51, 52, 53 }, + ['metrochg'] = { 51, 52, 53 }, + ['metrodur'] = { 51, 52, 53 }, + ['metroexc'] = { 51, 52, 53 }, + ['metroexp'] = { 51, 52, 53 }, + ['metroexp2'] = { 51, 52, 53 }, + ['metroexp3'] = { 51, 52, 53 }, + ['metroexp4'] = { 51, 52, 53 }, + ['metrof250'] = { 51, 52, 53 }, + ['metrovic'] = { 51, 52, 53 }, + ['metrovic2'] = { 51, 52, 53 }, + ['chp1200'] = { 54, 55, 56, 57 }, + ['chpbearcat'] = { 54, 55, 56, 57 }, + ['chpchg'] = { 54, 55, 56, 57 }, + ['chpchg2'] = { 54, 55, 56, 57 }, + ['chpchg3'] = { 54, 55, 56, 57 }, + ['chpchg4'] = { 54, 55, 56, 57 }, + ['chpchg5'] = { 54, 55, 56, 57 }, + ['chpchg6'] = { 54, 55, 56, 57 }, + ['chpchg7'] = { 54, 55, 56, 57 }, + ['chpdurango'] = { 54, 55, 56, 57 }, + ['chpdurango2'] = { 54, 55, 56, 57 }, + ['chpexp'] = { 54, 55, 56, 57 }, + ['chpfpiu'] = { 54, 55, 56, 57 }, + ['chpfpiu2'] = { 54, 55, 56, 57 }, + ['chpfpiu3'] = { 54, 55, 56, 57 }, + ['chpfpiu4'] = { 54, 55, 56, 57 }, + ['chpfpiu5'] = { 54, 55, 56, 57 }, + ['chpfpiu6'] = { 54, 55, 56, 57 }, + ['chpfpiu7'] = { 54, 55, 56, 57 }, + ['chpfpiu8'] = { 54, 55, 56, 57 }, + ['chpfpiuk9'] = { 54, 55, 56, 57 }, + ['chpram'] = { 54, 55, 56, 57 }, + ['chpsilverado'] = { 54, 55, 56, 57 }, + ['chpsub'] = { 54, 55, 56, 57 }, + ['chptahoe'] = { 54, 55, 56, 57 }, + ['chptahoe2'] = { 54, 55, 56, 57 }, + ['chptahoe3'] = { 54, 55, 56, 57 }, + ['chptahoe4'] = { 54, 55, 56, 57 }, + ['chptahoe5'] = { 54, 55, 56, 57 }, + ['chptahoe6'] = { 54, 55, 56, 57 }, + ['chptahoe7'] = { 54, 55, 56, 57 }, + ['chptahoek9'] = { 54, 55, 56, 57 }, + ['chpvic'] = { 54, 55, 56, 57 }, + ['lapd14tahoe1'] = { 51, 52, 53 }, + ['lapd14tahoe2'] = { 51, 52, 53 }, + ['lapd14tahoe3'] = { 51, 52, 53 }, + ['lapd14tahoe4'] = { 51, 52, 53 }, + ['lapd17funm'] = { 51, 52, 53 }, + ['lapd18chrgr'] = { 51, 52, 53 }, + ['lapd18funm'] = { 51, 52, 53 }, + ['lapd19durango'] = { 51, 52, 53 }, + ['lapd19funm'] = { 51, 52, 53 }, + ['lapd20chrgra'] = { 51, 52, 53 }, + ['lapd20chrgrb'] = { 51, 52, 53 }, + ['lapd20det'] = { 51, 52, 53 }, + ['lapd20fpiua'] = { 51, 52, 53 }, + ['lapd20fpiub'] = { 51, 52, 53 }, + ['lapd20fpiuburn'] = { 51, 52, 53 }, + ['lapd20fpiuc'] = { 51, 52, 53 }, + ['lapd20fpiud'] = { 51, 52, 53 }, + ['lapd20fpiunew'] = { 51, 52, 53 }, + ['lapd20fpiuoly'] = { 51, 52, 53 }, + ['lapd20sl'] = { 51, 52, 53 }, + ['lapd20talpra'] = { 51, 52, 53 }, + ['lapd20talprb'] = { 51, 52, 53 }, + ['lapd20tfpiu'] = { 51, 52, 53 }, + ['lapd20unm1'] = { 51, 52, 53 }, + ['lapd20unm2'] = { 51, 52, 53 }, + ['lapd24fpiu'] = { 51, 52, 53 }, + ['lapddp14chg'] = { 51, 52, 53 }, + ['lapddp14tau'] = { 51, 52, 53 }, + ['lapddp16exp'] = { 51, 52, 53 }, + ['lapddp18chg'] = { 51, 52, 53 }, + ['lapddp98vic1'] = { 51, 52, 53 }, + ['lapddp98vic2'] = { 51, 52, 53 }, + ['lapdexc'] = { 51, 52, 53 }, + ['lapdsub'] = { 51, 52, 53 }, + ['lapdtd08vic'] = { 51, 52, 53 }, + ['lasd20lp'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd20tahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd20tfs'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd20tunm'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdcharger'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdcrownvic'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdfpiu'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdlithium'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdparamount'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdsap'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdsd7100'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdtahoelan'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdtaurus'] = { 21, 22, 23, 24, 25, 25 }, + ['lasdvicslicktop'] = { 21, 22, 23, 24, 25, 25 }, + ['lsfdcmd'] = { 21, 22, 23, 24, 25, 25 }, + ['lsfdpickup'] = { 21, 22, 23, 24, 25, 25 }, + ['lspdpark2'] = { 21, 22, 23, 24, 25, 25 }, + ['lspdpark3'] = { 21, 22, 23, 24, 25, 25 }, + ['lspdvant'] = { 21, 22, 23, 24, 25, 25 }, + ['lspw1'] = { 21, 22, 23, 24, 25, 25 }, + ['lssdfpisa'] = { 21, 22, 23, 24, 25, 25 }, + ['lssdfpisi'] = { 21, 22, 23, 24, 25, 25 }, + ['met2'] = { 21, 22, 23, 24, 25, 25 }, + ['met3'] = { 21, 22, 23, 24, 25, 25 }, + ['metrocharger'] = { 21, 22, 23, 24, 25, 25 }, + ['metrofpiu'] = { 21, 22, 23, 24, 25, 25 }, + ['metrotrain'] = { 21, 22, 23, 24, 25, 25 }, + ['mtlengine'] = { 21, 22, 23, 24, 25, 25 }, + ['mtlengine2'] = { 21, 22, 23, 24, 25, 25 }, + ['pcar'] = { 21, 22, 23, 24, 25, 25 }, + ['pcar2'] = { 21, 22, 23, 24, 25, 25 }, + ['pcart'] = { 21, 22, 23, 24, 25, 25 }, + ['rcsd13fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['rcsd13fpiu2'] = { 15, 16, 17, 18, 19, 20 }, + ['rcsd16fpiu3'] = { 15, 16, 17, 18, 19, 20 }, + ['rcsd16fpiu4'] = { 15, 16, 17, 18, 19, 20 }, + ['rcsd20fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['rcsd20fpiu3'] = { 15, 16, 17, 18, 19, 20 }, + ['rcsdcaprice'] = { 15, 16, 17, 18, 19, 20 }, + ['rcsdcvpi'] = { 15, 16, 17, 18, 19, 20 }, + ['rcsdcvpi2'] = { 15, 16, 17, 18, 19, 20 }, + ['rcsdcvpi3'] = { 15, 16, 17, 18, 19, 20 }, + ['rcsdcvpi4'] = { 15, 16, 17, 18, 19, 20 }, + ['rcsdf150'] = { 15, 16, 17, 18, 19, 20 }, + ['rcsdf2502'] = { 15, 16, 17, 18, 19, 20 }, + ['rcsdtahoe'] = { 15, 16, 17, 18, 19, 20 }, + ['redondo1'] = { 21, 22, 23, 24, 25, 25 }, + ['redondo2'] = { 21, 22, 23, 24, 25, 25 }, + ['redondo3'] = { 21, 22, 23, 24, 25, 25 }, + ['riot3'] = { 21, 22, 23, 24, 25, 25 }, + ['sebtahoe'] = { 21, 22, 23, 24, 25, 25 }, + ['sheriffsar'] = { 21, 22, 23, 24, 25, 25 }, + ['SHOP00000'] = { 21, 22, 23, 24, 25, 25 }, + ['smpd16fpiu01'] = { 15, 16, 17, 18, 19, 20 }, + ['smpd16fpiu02'] = { 15, 16, 29, 31, 32, 18 }, + ['smpd16fpiu03'] = { 15, 16, 17, 18, 19, 20 }, + ['smpd16fpiu04'] = { 15, 16, 17, 18, 19, 20 }, + ['smpd16fpiu05'] = { 15, 16, 17, 18, 19, 20 }, + ['smpd16fpiu06'] = { 15, 16, 17, 18, 19, 20 }, + ['SMPDF150'] = { 15, 16, 17, 18, 19, 20 }, + ['smpdvic'] = { 15, 16, 17, 18, 19, 20 }, + ['vcsotahoe'] = { 15, 16, 17, 18, 19, 20 }, + ['vcsotahoe2'] = { 15, 16, 17, 18, 19, 20 }, + ['vcsotahoe3'] = { 15, 16, 17, 18, 19, 20 }, + ['vhpd1'] = { 21, 22, 23, 24, 25, 25 }, + ['whelentahoe20'] = { 15, 16, 17, 18, 19, 20 }, + ['LASDCVPI1'] = { 21, 22, 23, 24, 25, 25 }, + ['LASDCVPI2'] = { 21, 22, 23, 24, 25, 25 }, + ['LASDCVPI3'] = { 21, 22, 23, 24, 25, 25 }, + ['LASDSTCVPI1'] = { 21, 22, 23, 24, 25, 25 }, + ['gtfminivan'] = { 21, 22, 23, 24, 25, 25 }, + ['lsfdtruck'] = { 21, 22, 23, 24, 25, 25 }, + ['lsfdtruck2'] = { 21, 22, 23, 24, 25, 25 }, + ['17colorado'] = { 51, 52, 53 }, + ['centurion'] = { 21, 22, 23, 24, 25, 25 }, + ['centurionfib'] = { 21, 22, 23, 24, 25, 25 }, + ['centurionlssd'] = { 21, 22, 23, 24, 25, 25 }, + ['riot3'] = { 21, 22, 23, 24, 25, 25 }, + ['lapd09charger1'] = { 51, 52, 53 }, + ['lapd09charger2'] = { 51, 52, 53 }, + ['lapd09dual'] = { 51, 52, 53 }, + ['southlandexclusive'] = { 21, 22, 23, 24, 25, 25 }, + ['umcvpi'] = { 21, 22, 23, 24, 25, 25 }, + ['whelentahoe20'] = { 21, 22, 23, 24, 25, 25 }, + ['SH8172'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16asapbpalm'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16asapcpalm'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16asapdpalm'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16asappalm'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16fpiubpalm'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16fpiupalm'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16fpiupalm'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16rfrbpalm'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16rfrpalm'] = { 21, 22, 23, 24, 25, 25 }, + ['irvinepd16fpiu_43'] = { 15, 16, 29, 31, 32, 18 }, + ['irvinepd18taho_104'] = { 15, 16, 29, 31, 32, 18 }, + ['irvinepd20fpiu_09'] = { 15, 16, 29, 31, 32, 18 }, + ['irvinepd20fpiu_18'] = { 15, 16, 29, 31, 32, 18 }, + ['irvinepd20fpiu_31'] = { 15, 16, 29, 31, 32, 18 }, + ['caltransdram'] = { 21, 22, 23, 24, 25, 25 }, + ['caltranse350'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16asap'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd25fpiu'] = { 21, 22, 23, 24, 25, 26 }, + ['lasd16asapb'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16asapc'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16asapd'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16fpiu'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16fpiub'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16rfr'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16rfrb'] = { 21, 22, 23, 24, 25, 25 }, + ['01fordbrush'] = { 21, 22, 23, 24, 25, 25 }, + ['20ramcwr'] = { 21, 22, 23, 24, 25, 25 }, + ['20ramswr'] = { 21, 22, 23, 24, 25, 25 }, + ['f550amboc'] = { 21, 22, 23, 24, 25, 25 }, + ['arrowp'] = { 21, 22, 23, 24, 25, 25 }, + ['oldmack'] = { 21, 22, 23, 24, 25, 25 }, + ['squad350'] = { 21, 22, 23, 24, 25, 25 }, + ['16ramcsquad'] = { 21, 22, 23, 24, 25, 25 }, + ['2020MET'] = { 21, 22, 23, 24, 25, 25 }, + ['fmgtr'] = { 21, 22, 23, 24, 25, 25 }, + ['lafdxt6700'] = { 21, 22, 23, 24, 25, 25 }, + ['scorcher'] = { 21, 22, 23, 24, 25, 25 }, + ['lapdsub'] = { 21, 22, 23, 24, 25, 25 }, + ['lapdsub2'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd15k9b'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd15tahoeb'] = { 21, 22, 23, 24, 25, 25 }, + ['lssdfpisa'] = { 21, 22, 23, 24, 25, 25 }, + ['lssdfpisi'] = { 21, 22, 23, 24, 25, 25 }, + ['met2'] = { 21, 22, 23, 24, 25, 25 }, + ['met3'] = { 21, 22, 23, 24, 25, 25 }, + ['mustangrb'] = { 21, 22, 23, 24, 25, 25 }, + ['santaanapd08cvpi_963'] = { 15, 16, 17, 18, 19, 20 }, + ['santaanapd11cvpi_641'] = { 15, 16, 17, 18, 19, 20 }, + ['santaanapd11cvpi_908'] = { 15, 16, 17, 18, 19, 20 }, + ['santaanapd20fpiu_622'] = { 15, 16, 17, 18, 19, 20 }, + ['santaanapd20fpiu_913'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd13fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd13fpiu2'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd13fpiu2'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd16fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd16fpiu2'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd16fpiu3'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd20fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsdchrgr'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsdcvpi'] = { 15, 16, 17, 18, 19, 20 }, + ['SDSC6'] = { 15, 16, 17, 18, 19, 20 }, + ['workf150'] = { 21, 22, 23, 24, 25, 25 }, + ['metro1'] = { 21, 22, 23, 24, 25, 25 }, + ['metro2'] = { 21, 22, 23, 24, 25, 25 }, + ['metro3'] = { 21, 22, 23, 24, 25, 25 }, + ['metro4'] = { 21, 22, 23, 24, 25, 25 }, + ['metro5'] = { 21, 22, 23, 24, 25, 25 }, + ['metro6'] = { 21, 22, 23, 24, 25, 25 }, + ['metro7'] = { 21, 22, 23, 24, 25, 25 }, + ['metrovan'] = { 21, 22, 23, 24, 25, 25 }, + ['23UNMARKsubun'] = { 21, 22, 23, 24, 25, 25 }, + ['23lapdlasdsuburls'] = { 21, 22, 23, 24, 25, 25 }, + ['LASDram1500'] = { 21, 22, 23, 24, 25, 25 }, + ['psp18chgrlib1'] = { 21, 22, 23, 24, 25, 25 }, + ['psp23chgrlib2'] = { 21, 22, 23, 24, 25, 25 }, + ['psp24durangolib2'] = { 21, 22, 23, 24, 25, 25 }, + ['psp24fpiulib2'] = { 21, 22, 23, 24, 25, 25 }, + ['edtrackhawk'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16asap'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16asapb'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16asapc'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16asapd'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16fpiu'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16fpiub'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16rfr'] = { 21, 22, 23, 24, 25, 25 }, + ['lasd16rfrb'] = { 21, 22, 23, 24, 25, 25 }, + ['secrsub'] = { 21, 22, 23, 24, 25, 25 }, + ['sscat'] = { 21, 22, 23, 24, 25, 25 }, + ['sspres'] = { 21, 22, 23, 24, 25, 25 }, + ['subsec'] = { 21, 22, 23, 24, 25, 25 }, + ['stpickup'] = { 21, 22, 23, 24, 25, 25 }, + ['bcsoalamo'] = { 21, 22, 23, 24, 25, 25 }, + ['lssdalamo'] = { 21, 22, 23, 24, 25, 25 }, + ['sanfirealamo'] = { 21, 22, 23, 24, 25, 25 }, + ['umkalamo'] = { 21, 22, 23, 24, 25, 25 }, + ['bcat'] = { 21, 22, 23, 24, 25, 25 }, + ['bcat1'] = { 21, 22, 23, 24, 25, 25 }, + ['bcat2'] = { 21, 22, 23, 24, 25, 25 }, + ['bcat3'] = { 21, 22, 23, 24, 25, 25 }, + ['sheriffalamo'] = { 21, 22, 23, 24, 25, 25 }, + ['sheriffcq4'] = { 21, 22, 23, 24, 25, 25 }, + ['sherifffug'] = { 21, 22, 23, 24, 25, 25 }, + ['sheriffinsurgent'] = { 21, 22, 23, 24, 25, 25 }, + ['sheriffoss'] = { 21, 22, 23, 24, 25, 25 }, + ['sheriffroamer'] = { 21, 22, 23, 24, 25, 25 }, + ['sheriffrumpo'] = { 21, 22, 23, 24, 25, 25 }, + ['sheriffscout'] = { 21, 22, 23, 24, 25, 25 }, + ['sheriffscoutnew'] = { 21, 22, 23, 24, 25, 25 }, + ['sheriffstalker'] = { 21, 22, 23, 24, 25, 25 }, + ['sheriffthrust'] = { 21, 22, 23, 24, 25, 25 }, + ['Commandcenter'] = { 21, 22, 23, 24, 25, 25 }, + ['commandtruck'] = { 21, 22, 23, 24, 25, 25 }, + ['commandtruckr'] = { 21, 22, 23, 24, 25, 25 }, + ['Commandcenterr'] = { 21, 22, 23, 24, 25, 25 }, + ['n16exp'] = { 21, 22, 23, 24, 25, 26 }, + ['nf12cap'] = { 21, 22, 23, 24, 25, 26 }, + ['nf13exp'] = { 21, 22, 23, 24, 25, 26 }, + ['nf14charg'] = { 21, 22, 23, 24, 25, 26 }, + ['nf14tah'] = { 21, 22, 23, 24, 25, 26 }, + ['nf16exp'] = { 21, 22, 23, 24, 25, 26 }, + ['nf18charg'] = { 21, 22, 23, 24, 25, 26 }, + ['nf18f150'] = { 21, 22, 23, 24, 25, 26 }, + ['nf18taur'] = { 21, 22, 23, 24, 25, 26 }, + ['nf19tah'] = { 21, 22, 23, 24, 25, 26 }, + ['nf20dur'] = { 21, 22, 23, 24, 25, 26 }, + ['nf20exp'] = { 21, 22, 23, 24, 25, 26 }, + ['nf21tah'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdalamonew1'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdalamonew2'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdmule'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdscout1'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdscout2'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdscoutnew1'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdscoutnew2'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdscoutnew3'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdsecurity1'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdstanier1'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdstanier2'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdumk1'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdumk2'] = { 21, 22, 23, 24, 25, 26 }, + ['lssdumk3'] = { 21, 22, 23, 24, 25, 26 }, + ['hab23charger'] = { 21, 22, 23, 24, 25, 26 }, + ['hab23chargerb'] = { 21, 22, 23, 24, 25, 26 }, + ['medic6'] = { 45, 16, 40, 38, 48, 31 }, + ['medic5'] = { 45, 16, 40, 38, 48, 31 }, + ['medic4'] = { 45, 16, 40, 38, 48, 31 }, + ['medic3'] = { 45, 16, 40, 38, 48, 31 }, + ['medic1'] = { 45, 16, 40, 38, 48, 31 }, + ['medic1a'] = { 45, 16, 40, 38, 48, 31 }, + ['338pt'] = { 45, 48, 13, 46, 47, 49 }, + ['359ebilt'] = { 45, 48, 13, 46, 47, 49 }, + ['sbcsd08tahoe'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd13fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd13fpiu2'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd16fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd16fpiu2'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd16fpiu3'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd18tahoe'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd20fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd20fpiu2'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd20fpiuX'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsd21durango'] = { 15, 16, 17, 18, 19, 20 }, + ['sbcsdcharger'] = { 15, 16, 17, 18, 19, 20 }, + ['smcso20fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['smcso25fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeach1'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeach3'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeach4'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeachk9'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeachold1'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeachold2'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeachold3'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeachold4'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeachold5'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeachold6'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeachold7'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeachslicktop'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeachtahoe'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeachu1'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeachu2'] = { 15, 16, 17, 18, 19, 20 }, + ['longbeachu3'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsdk9hoe'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsd24hoe1'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsd24hoe'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsd24durst'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsd24dur'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsd20fpiutrans'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsd20fpiust'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsd20fpiu2'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsd20fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsd18tahoest'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsd18tahoe'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsd18dur'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsd16fpiust'] = { 15, 16, 17, 18, 19, 20 }, + ['ocsd16fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['sdpd23fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['sdpd21tahoe'] = { 15, 16, 17, 18, 19, 20 }, + ['sdpd20fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['sdpd18tahoe'] = { 15, 16, 17, 18, 19, 20 }, + ['sdpd16fwatch'] = { 15, 16, 17, 18, 19, 20 }, + ['sdpd16fpiust'] = { 15, 16, 17, 18, 19, 20 }, + ['sdpd16fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['sdpd13fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['uc_charger'] = { 15, 16, 17, 18, 19, 20 }, + ['tp_raptor'] = { 15, 16, 17, 18, 19, 20 }, + ['slick25durango'] = { 15, 16, 17, 18, 19, 20 }, + ['slick23tahoe'] = { 15, 16, 17, 18, 19, 20 }, + ['slick23charger'] = { 15, 16, 17, 18, 19, 20 }, + ['slick21charg'] = { 15, 16, 17, 18, 19, 20 }, + ['slick20fpiu'] = { 15, 16, 17, 18, 19, 20 }, + ['slick20durango'] = { 15, 16, 17, 18, 19, 20 }, + ['os_jus18taurus'] = { 15, 16, 17, 18, 19, 20 }, + ['kghoulre'] = { 15, 16, 17, 18, 19, 20 }, + ['hard23charger'] = { 15, 16, 17, 18, 19, 20 }, + ['2020charger'] = { 15, 16, 17, 18, 19, 20 }, + ['23heatcam'] = { 15, 16, 17, 18, 19, 20 }, + ['uc23suburban'] = { 15, 16, 17, 18, 19, 20 }, + ['dps16explorer'] = { 15, 28, 29, 30, 31, 32 }, + ['dps16explorers'] = { 15, 28, 29, 30, 31, 32 }, + ['dps18charger2'] = { 15, 28, 29, 30, 31, 32 }, + ['dps18chargers'] = { 15, 28, 29, 30, 31, 32 }, + ['dps18chargeru'] = { 15, 28, 29, 30, 31, 32 }, + ['dps20k9tahoe'] = { 15, 28, 29, 30, 31, 32 }, + ['dps20tahoe2'] = { 15, 28, 29, 30, 31, 32 }, + ['dps20tahoeslick'] = { 15, 28, 29, 30, 31, 32 }, + ['dps21durango'] = { 15, 28, 29, 30, 31, 32 }, + ['dps21explorer'] = { 15, 28, 29, 30, 31, 32 }, + ['dps21k9f150'] = { 15, 28, 29, 30, 31, 32 }, + ['dps21silv'] = { 15, 28, 29, 30, 31, 32 }, + ['dps21silv1500'] = { 15, 28, 29, 30, 31, 32 }, + ['dps21tahoe'] = { 15, 28, 29, 30, 31, 32 }, + ['dps21tahoes'] = { 15, 28, 29, 30, 31, 32 }, + ['dps22tahoe'] = { 15, 28, 29, 30, 31, 32 }, + ['dps22tahoegrap'] = { 15, 28, 29, 30, 31, 32 }, + ['dps23f150'] = { 15, 28, 29, 30, 31, 32 }, + ['dps23silv1500'] = { 15, 28, 29, 30, 31, 32 }, + ['dps23tahoesg'] = { 15, 28, 29, 30, 31, 32 }, + ['dps23tahoesgu'] = { 15, 28, 29, 30, 31, 32 }, + ['18chargerb'] = { 15, 28, 29, 30, 31, 32 }, + ['20fpiu20'] = { 15, 28, 29, 30, 31, 32 }, + ['18charger'] = { 15, 28, 29, 30, 31, 32 }, + ['hab23charger'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsd13fpiu'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsd13fpiu2'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsd16fpiu'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsd16fpiu2'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsd16fpiu3'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsd16fpiu4'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsd20fpiu'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsd20fpiu3'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsdcaprice'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsdcvpi'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsdcvpi2'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsdcvpi3'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsdcvpi4'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsdf150'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsdf250'] = { 15, 28, 29, 30, 31, 32 }, + ['rcsdf2502'] = { 15, 28, 29, 30, 31, 32 }, + ['vpd3'] = { 15, 28, 29, 30, 31, 32 }, + ['vpd3st'] = { 15, 28, 29, 30, 31, 32 }, + ['vpd3uc'] = { 15, 28, 29, 30, 31, 32 }, + ['258charger'] = { 54, 55, 56, 57, 58, 59 }, + ['275charger'] = { 54, 55, 56, 57, 58, 59 }, + ['296charger'] = { 54, 55, 56, 57, 58, 59 }, + ['351charger'] = { 54, 55, 56, 57, 58, 59 }, + ['554charger'] = { 54, 55, 56, 57, 58, 59 }, + ['643charger'] = { 54, 55, 56, 57, 58, 59 }, + ['689charger'] = { 54, 55, 56, 57, 58, 59 }, + ['751charger'] = { 54, 55, 56, 57, 58, 59 }, + ['767charger'] = { 54, 55, 56, 57, 58, 59 }, + ['891charger'] = { 54, 55, 56, 57, 58, 59 }, + ['940charger'] = { 54, 55, 56, 57, 58, 59 }, + ['960charger'] = { 54, 55, 56, 57, 58, 59 }, + ['704durango'] = { 54, 55, 56, 57, 58, 59 }, + ['146charger'] = { 54, 55, 56, 57, 58, 59 }, + ['122charger'] = { 54, 55, 56, 57, 58, 59 }, + ['2010cvpipov'] = { 54, 55, 56, 57, 58, 59 }, + ['7644camaro'] = { 54, 55, 56, 57, 58, 59 }, + ['843tahoe'] = { 54, 55, 56, 57, 58, 59 }, + ['438camaro'] = { 54, 55, 56, 57, 58, 59 }, + ['104charger'] = { 54, 55, 56, 57, 58, 59 }, + ['4003cpd'] = { 54, 55, 56, 57, 58, 59 }, + ['1830'] = { 54, 55, 56, 57, 58, 59 }, + ['1822'] = { 54, 55, 56, 57, 58, 59 }, + ['1806charger'] = { 54, 55, 56, 57, 58, 59 }, + ['352charger'] = { 54, 55, 56, 57, 58, 59 }, + ['878truck'] = { 54, 55, 56, 57, 58, 59 }, + ['975tahoe'] = { 54, 55, 56, 57, 58, 59 }, + ['gspcharger'] = { 54, 55, 56, 57, 58, 59 }, + ['222'] = { 54, 55, 56, 57, 58, 59 }, + ['283'] = { 54, 55, 56, 57, 58, 59 }, + ['452'] = { 54, 55, 56, 57, 58, 59 }, + ['883'] = { 54, 55, 56, 57, 58, 59 }, + ['gspmustang'] = { 54, 55, 56, 57, 58, 59 }, + ['hab23chargerb'] = { 54, 55, 56, 57, 58, 59 }, + ['lasd20piu'] = { 21, 22, 23 }, + ['vcsd25piu'] = { 21, 22, 23 }, + ['2010cvpipov'] = { 45, 16,40, 38, 48, 31 }, + ['spartan3c'] = { 45, 16,40, 38, 48, 31 }, + [' '] = { 45, 16,40, 38, 48, 31 }, + [' '] = { 45, 16,40, 38, 48, 31 }, + [' '] = { 45, 16,40, 38, 48, 31 }, + [' '] = { 45, 16,40, 38, 48, 31 }, + [' '] = { 45, 16,40, 38, 48, 31 }, + [' '] = { 21, 22, 23 }, + ['jus16fpis'] = { 21, 22, 23 }, + ['lasdf150u'] = { 21, 22, 23 }, + ['lasd20fasap'] = { 21, 22, 23 }, + ['lasd20funm'] = { 21, 22, 23 }, + ['EODT'] = { 21, 22, 23 }, + ['eodb1'] = { 21, 22, 23 }, + ['eod2'] = { 21, 22, 23 }, + ['25f150xlt'] = { 21, 22, 23 }, + ['lapd13tahoe'] = { 21, 22, 23 }, + [' '] = { 21, 22, 23 }, + [' '] = { 21, 22, 23 }, + ['lapd20fpiua'] = { 51, 52, 53 }, + ['lapd20fpiub'] = { 51, 52, 53 }, + ['lapd20sl'] = { 51, 52, 53 }, + ['lapd20talpra'] = { 51, 52, 53 }, + ['lapd20talprb'] = { 51, 52, 53 }, + ['lapd20unm1'] = { 51, 52, 53 }, + ['lapd20unm2'] = { 51, 52, 53 }, + ['258charger'] = { 39, 58, 59, 18, 31, 32 }, + ['275charger'] = { 39, 58, 59, 18, 31, 32 }, + ['296charger'] = { 39, 58, 59, 18, 31, 32 }, + ['351charger'] = { 39, 58, 59, 18, 31, 32 }, + ['554charger'] = { 39, 58, 59, 18, 31, 32 }, + ['643charger'] = { 39, 58, 59, 18, 31, 32 }, + ['689charger'] = { 39, 58, 59, 18, 31, 32 }, + ['751charger'] = { 39, 58, 59, 18, 31, 32 }, + ['767charger'] = { 39, 58, 59, 18, 31, 32 }, + ['891charger'] = { 39, 58, 59, 18, 31, 32 }, + ['940charger'] = { 39, 58, 59, 18, 31, 32 }, + ['960charger'] = { 39, 58, 59, 18, 31, 32 }, + ['704durango'] = { 39, 58, 59, 18, 31, 32 }, + ['146charger'] = { 39, 58, 59, 18, 31, 32 }, + ['122charger'] = { 39, 58, 59, 18, 31, 32 }, + ['7644camaro'] = { 39, 58, 59, 18, 31, 32 }, + ['843tahoe'] = { 39, 58, 59, 18, 31, 32 }, + ['438camaro'] = { 39, 58, 59, 18, 31, 32 }, + ['104charger'] = { 39, 58, 59, 18, 31, 32 }, + ['4003cpd'] = { 39, 58, 59, 18, 31, 32 }, + ['1830'] = { 39, 58, 59, 18, 31, 32 }, + ['1806charger'] = { 39, 58, 59, 18, 31, 32 }, + ['352charger'] = { 39, 58, 59, 18, 31, 32 }, + ['878truck'] = { 39, 58, 59, 18, 31, 32 }, + ['975tahoe'] = { 39, 58, 59, 18, 31, 32 }, + ['615'] = { 39, 58, 59, 18, 31, 32 }, + ['gspcharger'] = { 39, 58, 59, 18, 31, 32 }, + ['gt24non'] = { 39, 58, 59, 18, 31, 32 }, + ['128durango'] = { 39, 58, 59, 18, 31, 32 }, + ['640'] = { 39, 58, 59, 18, 31, 32 }, + ['704'] = { 39, 58, 59, 18, 31, 32 }, + ['751'] = { 39, 58, 59, 18, 31, 32 }, + ['128'] = { 39, 58, 59, 18, 31, 32 }, + ['asp14charg'] = { 39, 58, 59, 18, 31, 32 }, + ['asp16fpiu'] = { 39, 58, 59, 18, 31, 32 }, + ['asp18dur'] = { 39, 58, 59, 18, 31, 32 }, + ['asp18durst'] = { 39, 58, 59, 18, 31, 32 }, + ['asp18tahoe1'] = { 39, 58, 59, 18, 31, 32 }, + ['asp18tahoe2'] = { 39, 58, 59, 18, 31, 32 }, + ['asp21dur'] = { 39, 58, 59, 18, 31, 32 }, + ['asp21durst'] = { 39, 58, 59, 18, 31, 32 }, + ['aspa9'] = { 39, 58, 59, 18, 31, 32 }, + ['aspa46'] = { 39, 58, 59, 18, 31, 32 }, + ['aspdbenton'] = { 39, 58, 59, 18, 31, 32 }, + ['aspg3'] = { 39, 58, 59, 18, 31, 32 }, + ['aspkdavis'] = { 39, 58, 59, 18, 31, 32 }, + ['aspst1'] = { 39, 58, 59, 18, 31, 32 }, + ['fhp_20fpiu2'] = { 39, 58, 59, 18, 31, 32 }, + ['fhp_20fpiu2st'] = { 39, 58, 59, 18, 31, 32 }, + ['fhp_charger3'] = { 39, 58, 59, 18, 31, 32 }, + ['fhp_charger3bw'] = { 39, 58, 59, 18, 31, 32 }, + ['fhp_charger3st'] = { 39, 58, 59, 18, 31, 32 }, + ['fhp_charger3ta'] = { 39, 58, 59, 18, 31, 32 }, + ['fhp_charger3uc'] = { 39, 58, 59, 18, 31, 32 }, + ['21silvst'] = { 39, 58, 59, 18, 31, 32 }, + ['21silvstbb'] = { 39, 58, 59, 18, 31, 32 }, + ['1601'] = { 39, 58, 59, 18, 31, 32 }, + ['1609'] = { 39, 58, 59, 18, 31, 32 }, + ['1615'] = { 39, 58, 59, 18, 31, 32 }, + ['bostoncvpi'] = { 39, 58, 59, 18, 31, 32 }, + ['civ25durango'] = { 39, 58, 59, 18, 31, 32 }, + ['csp23chgr'] = { 39, 58, 59, 18, 31, 32 }, + ['ecsortrango'] = { 39, 58, 59, 18, 31, 32 }, + ['fhpmustang'] = { 39, 58, 59, 18, 31, 32 }, + ['fs23chgr'] = { 39, 58, 59, 18, 31, 32 }, + ['fs23chgrbb'] = { 39, 58, 59, 18, 31, 32 }, + ['fs23durango'] = { 39, 58, 59, 18, 31, 32 }, + ['fs23durangobb'] = { 39, 58, 59, 18, 31, 32 }, + ['fs23tahoe'] = { 39, 58, 59, 18, 31, 32 }, + ['fs23tahoebb'] = { 39, 58, 59, 18, 31, 32 }, + ['fs25f150bb'] = { 39, 58, 59, 18, 31, 32 }, + ['hmlegsilv'] = { 39, 58, 59, 18, 31, 32 }, + ['hmlegsilvbb'] = { 39, 58, 59, 18, 31, 32 }, + ['isp24tahoe'] = { 39, 58, 59, 18, 31, 32 }, + [' '] = { 39, 58, 59, 18, 31, 32 }, + ['isp25durango'] = { 39, 58, 59, 18, 31, 32 }, + ['isp25durangopb'] = { 39, 58, 59, 18, 31, 32 }, + ['isp25durangopb3'] = { 39, 58, 59, 18, 31, 32 }, + ['ksp23tahoe'] = { 39, 58, 59, 18, 31, 32 }, + ['ksp23tahoeslick'] = { 39, 58, 59, 18, 31, 32 }, + ['ksp25durango'] = { 39, 58, 59, 18, 31, 32 }, + ['leg25durango'] = { 39, 58, 59, 18, 31, 32 }, + ['lib16fpiurb'] = { 39, 58, 59, 18, 31, 32 }, + ['mshp13explorer'] = { 39, 58, 59, 18, 31, 32 }, + ['mshp16explorer'] = { 39, 58, 59, 18, 31, 32 }, + ['mshp16explorerst'] = { 39, 58, 59, 18, 31, 32 }, + ['mshpcharger'] = { 39, 58, 59, 18, 31, 32 }, + ['mshpchargerst'] = { 39, 58, 59, 18, 31, 32 }, + ['mshpdurango'] = { 39, 58, 59, 18, 31, 32 }, + ['mshpdurangost'] = { 39, 58, 59, 18, 31, 32 }, + ['mshpstang'] = { 39, 58, 59, 18, 31, 32 }, + ['mst16fpiu'] = { 39, 58, 59, 18, 31, 32 }, + ['mst25durango'] = { 39, 58, 59, 18, 31, 32 }, + ['psp24tahoe'] = { 39, 58, 59, 18, 31, 32 }, + ['sos23chgrrb'] = { 39, 58, 59, 18, 31, 32 }, + ['wh23chgr'] = { 39, 58, 59, 18, 31, 32 }, + ['wh23chgrbb'] = { 39, 58, 59, 18, 31, 32 }, + ['st25'] = { 39, 58, 59, 18, 31, 32 }, + ['uc18chargbb'] = { 39, 58, 59, 18, 31, 32 }, + ['gsp25fpiu'] = { 39, 58, 59, 18, 31, 32 }, + ['gspmustang'] = { 39, 58, 59, 18, 31, 32 }, + ['fcsocharger'] = { 39, 58, 59, 18, 31, 32 }, + ['csupool1'] = { 39, 58, 59, 18, 31, 32 }, + ['ccso5'] = { 39, 58, 59, 18, 31, 32 }, + ['apdslickchgr2'] = { 39, 58, 59, 18, 31, 32 }, + ['apdfpiuwestin'] = { 39, 58, 59, 18, 31, 32 }, + ['apdfpiu'] = { 39, 58, 59, 18, 31, 32 }, + ['apdcharger2v2'] = { 39, 58, 59, 18, 31, 32 }, + ['apdcharger2'] = { 39, 58, 59, 18, 31, 32 }, + + ['7675'] = { 39, 58, 59, 18, 31, 32 }, + ['7673durango'] = { 39, 58, 59, 18, 31, 32 }, + ['7671durango'] = { 39, 58, 59, 18, 31, 32 }, + ['7548charger'] = { 39, 58, 59, 18, 31, 32 }, + ['7513'] = { 39, 58, 59, 18, 31, 32 }, + ['7218'] = { 39, 58, 59, 18, 31, 32 }, + ['883charger'] = { 39, 58, 59, 18, 31, 32 }, + ['842explorer'] = { 39, 58, 59, 18, 31, 32 }, + ['797'] = { 39, 58, 59, 18, 31, 32 }, + ['749mustang'] = { 39, 58, 59, 18, 31, 32 }, + ['746charger'] = { 39, 58, 59, 18, 31, 32 }, + ['713mustang'] = { 39, 58, 59, 18, 31, 32 }, + ['708'] = { 39, 58, 59, 18, 31, 32 }, + ['703explorer'] = { 39, 58, 59, 18, 31, 32 }, + ['536durango'] = { 39, 58, 59, 18, 31, 32 }, + ['478'] = { 39, 58, 59, 18, 31, 32 }, + ['423'] = { 39, 58, 59, 18, 31, 32 }, + ['367charger'] = { 39, 58, 59, 18, 31, 32 }, + ['337charger'] = { 39, 58, 59, 18, 31, 32 }, + ['247'] = { 39, 58, 59, 18, 31, 32 }, + ['223'] = { 39, 58, 59, 18, 31, 32 }, + ['187charger'] = { 39, 58, 59, 18, 31, 32 }, + ['181'] = { 39, 58, 59, 18, 31, 32 }, + ['146'] = { 39, 58, 59, 18, 31, 32 }, + ['134'] = { 39, 58, 59, 18, 31, 32 }, + ['119charger'] = { 39, 58, 59, 18, 31, 32 }, + ['114charger'] = { 39, 58, 59, 18, 31, 32 }, + ['25rangovalor'] = { 39, 58, 59, 18, 31, 32 }, + ['25rangoslick'] = { 39, 58, 59, 18, 31, 32 }, + ['01'] = { 39, 58, 59, 18, 31, 32 }, + ['20westinfpiu2'] = { 39, 58, 59, 18, 31, 32 }, + [' '] = { 39, 58, 59, 18, 31, 32 }, + [' '] = { 39, 58, 59, 18, 31, 32 }, + [' '] = { 39, 58, 59, 18, 31, 32 }, + [' '] = { 39, 58, 59, 18, 31, 32 }, + [' '] = { 39, 58, 59, 18, 31, 32 }, + [' '] = { 39, 58, 59, 18, 31, 32 }, + [' '] = { 39, 58, 59, 18, 31, 32 }, + [' '] = { 39, 58, 59, 18, 31, 32 }, + +} \ No newline at end of file diff --git a/resources/[EGRP-Map-Addons]/lvc/UTIL/cl_lvc.lua b/resources/[EGRP-Map-Addons]/lvc/UTIL/cl_lvc.lua new file mode 100644 index 000000000..7f5318456 --- /dev/null +++ b/resources/[EGRP-Map-Addons]/lvc/UTIL/cl_lvc.lua @@ -0,0 +1,861 @@ +--[[ +--------------------------------------------------- +LUXART VEHICLE CONTROL V3 (FOR FIVEM) +--------------------------------------------------- +Coded by Lt.Caine +ELS Clicks by Faction +Additional Modification by TrevorBarns +--------------------------------------------------- +FILE: cl_lvc.lua +PURPOSE: Core Functionality and User Input +--------------------------------------------------- +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 . +--------------------------------------------------- +]] + +--GLOBAL VARIABLES used in cl_ragemenu, UTILs, and plug-ins. +-- GENERAL VARIABLES +key_lock = false +playerped = nil +last_veh = nil +veh = nil +trailer = nil +player_is_emerg_driver = false +debug_mode = false + +-- MAIN SIREN SETTINGS +tone_main_reset_standby = reset_to_standby_default +tone_airhorn_intrp = airhorn_interrupt_default +park_kill = park_kill_default + +--LOCAL VARIABLES +local radio_wheel_active = false + +local count_bcast_timer = 0 +local delay_bcast_timer = 300 + +local count_sndclean_timer = 0 +local delay_sndclean_timer = 400 + +local actv_ind_timer = false +local count_ind_timer = 0 +local delay_ind_timer = 180 + +actv_lxsrnmute_temp = false +local srntone_temp = 0 +local dsrn_mute = true +local lights_on = false +local new_tone = nil +local tone_mem_id = nil +local tone_mem_option = nil +local default_tone = nil +local default_tone_option = nil + +state_indic = {} +state_lxsiren = {} +state_pwrcall = {} +state_airmanu = {} + +actv_manu = nil +actv_horn = nil + +local ind_state_o = 0 +local ind_state_l = 1 +local ind_state_r = 2 +local ind_state_h = 3 + +local snd_lxsiren = {} +local snd_pwrcall = {} +local snd_airmanu = {} + +-- Local fn forward declaration +local RegisterKeyMaps, MakeOrdinal + +----------------THREADED FUNCTIONS---------------- +-- Set check variable `player_is_emerg_driver` if player is driver of emergency vehicle. +-- Disables controls faster than previous thread. +CreateThread(function() + if GetResourceState('lux_vehcontrol') ~= 'started' and GetResourceState('lux_vehcontrol') ~= 'starting' then + if GetCurrentResourceName() == 'lvc' then + if community_id ~= nil and community_id ~= '' then + while true do + playerped = GetPlayerPed(-1) + --IS IN VEHICLE + player_is_emerg_driver = false + if IsPedInAnyVehicle(playerped, false) then + veh = GetVehiclePedIsUsing(playerped) + _, trailer = GetVehicleTrailerVehicle(veh) + --IS DRIVER + if GetPedInVehicleSeat(veh, -1) == playerped then + --IS EMERGENCY VEHICLE + if GetVehicleClass(veh) == 18 then + player_is_emerg_driver = true + DisableControlAction(0, 80, true) -- INPUT_VEH_CIN_CAM + DisableControlAction(0, 86, true) -- INPUT_VEH_HORN + DisableControlAction(0, 172, true) -- INPUT_CELLPHONE_UP + end + end + end + Wait(1) + end + else + Wait(1000) + HUD:ShowNotification(Lang:t('error.missing_community_id_frontend'), true) + UTIL:Print(Lang:t('error.missing_community_id_console'), true) + end + else + Wait(1000) + HUD:ShowNotification(Lang:t('error.invalid_resource_name_frontend'), true) + UTIL:Print(Lang:t('error.invalid_resource_name_console'), true) + end + else + Wait(1000) + HUD:ShowNotification(Lang:t('error.resource_conflict_frontend'), true) + UTIL:Print(Lang:t('error.resource_conflict_console'), true) + end +end) + +--On resource start/restart +CreateThread(function() + debug_mode = GetResourceMetadata(GetCurrentResourceName(), 'debug_mode', 0) == 'true' + TriggerEvent('chat:addSuggestion', Lang:t('command.lock_command'), Lang:t('command.lock_desc')) + SetNuiFocus( false ) + + UTIL:FixOversizeKeys(SIREN_ASSIGNMENTS) + RegisterKeyMaps() + STORAGE:SetBackupTable() +end) + +-- Auxiliary Control Handling +-- Handles radio wheel controls and default horn on siren change playback. +CreateThread(function() + while true do + if player_is_emerg_driver then + -- RADIO WHEEL + if IsControlPressed(0, 243) and AUDIO.radio_masterswitch then + while IsControlPressed(0, 243) do + radio_wheel_active = true + SetControlNormal(0, 85, 1.0) + Wait(0) + end + Wait(100) + radio_wheel_active = false + else + DisableControlAction(0, 85, true) -- INPUT_VEH_RADIO_WHEEL + SetVehicleRadioEnabled(veh, false) + end + end + Wait(0) + end +end) + +------ON VEHICLE EXIT EVENT TRIGGER------ +CreateThread(function() + while true do + if player_is_emerg_driver then + while playerped ~= nil and veh ~= nil do + if GetIsTaskActive(playerped, 2) and GetVehiclePedIsIn(ped, true) then + TriggerEvent('lvc:onVehicleExit') + Wait(1000) + end + Wait(0) + end + end + Wait(1000) + end +end) + +------VEHICLE CHANGE DETECTION AND TRIGGER------ +CreateThread(function() + while true do + if player_is_emerg_driver and veh ~= nil then + if last_veh == nil then + TriggerEvent('lvc:onVehicleChange') + else + if last_veh ~= veh then + TriggerEvent('lvc:onVehicleChange') + end + end + end + Wait(1000) + end +end) + +------------REGISTERED VEHICLE EVENTS------------ +--Kill siren on Exit +RegisterNetEvent('lvc:onVehicleExit') +AddEventHandler('lvc:onVehicleExit', function() + if park_kill_masterswitch and park_kill then + if not tone_main_reset_standby and state_lxsiren[veh] ~= 0 then + UTIL:SetToneByID('MAIN_MEM', state_lxsiren[veh]) + end + SetLxSirenStateForVeh(veh, 0) + SetPowercallStateForVeh(veh, 0) + SetAirManuStateForVeh(veh, 0) + HUD:SetItemState('siren', false) + HUD:SetItemState('horn', false) + count_bcast_timer = delay_bcast_timer + end +end) + +RegisterNetEvent('lvc:onVehicleChange') +AddEventHandler('lvc:onVehicleChange', function() + last_veh = veh + UTIL:UpdateApprovedTones(veh) + Wait(100) --waiting for JS event handler + STORAGE:ResetSettings() + UTIL:BuildToneOptions() + STORAGE:LoadSettings() + HUD:RefreshHudItemStates() + SetVehRadioStation(veh, 'OFF') + Wait(500) + SetVehRadioStation(veh, 'OFF') +end) + +--------------REGISTERED COMMANDS--------------- +--Toggle Debug Mode +RegisterCommand(Lang:t('command.debug_command'), function(source, args) + debug_mode = not debug_mode + HUD:ShowNotification(Lang:t('info.debug_mode_frontend', {state = debug_mode}), true) + UTIL:Print(Lang:t('info.debug_mode_console', {state = debug_mode}), true) + if debug_mode then + TriggerEvent('lvc:onVehicleChange') + end +end) + +--Toggle LUX lock command +RegisterCommand(Lang:t('command.lock_command'), function(source, args) + if player_is_emerg_driver then + key_lock = not key_lock + AUDIO:Play('Key_Lock', AUDIO.lock_volume, true) + HUD:SetItemState('lock', key_lock) + --if HUD is visible do not show notification + if not HUD:GetHudState() then + if key_lock then + HUD:ShowNotification(Lang:t('info.locked'), true) + else + HUD:ShowNotification(Lang:t('info.unlocked'), true) + end + end + end +end) + +RegisterKeyMapping(Lang:t('command.lock_command'), Lang:t('control.lock_desc'), 'keyboard', lockout_default_hotkey) + +------------------------------------------------ +-------------------FUNCTIONS-------------------- +------------------------------------------------ +------------------------------------------------ +--Dynamically Run RegisterCommand and KeyMapping functions for all 14 possible sirens +--Then at runtime 'slide' all sirens down removing any restricted sirens. +RegisterKeyMaps = function() + for i, _ in ipairs(SIRENS) do + if i ~= 1 then + local command = '_lvc_siren_' .. i-1 + local description = Lang:t('control.siren_control_desc', {ord_num = MakeOrdinal(i-1)}) + + RegisterCommand(command, function(source, args) + if veh ~= nil and player_is_emerg_driver ~= nil then + if IsVehicleSirenOn(veh) and player_is_emerg_driver and not key_lock then + local proposed_tone = UTIL:GetToneAtPos(i) + local tone_option = UTIL:GetToneOption(proposed_tone) + if i-1 < #UTIL:GetApprovedTonesTable() then + if tone_option ~= nil then + if tone_option == 1 or tone_option == 3 then + if ( state_lxsiren[veh] ~= proposed_tone or state_lxsiren[veh] == 0 ) then + HUD:SetItemState('siren', true) + AUDIO:Play('Upgrade', AUDIO.upgrade_volume) + SetLxSirenStateForVeh(veh, proposed_tone) + count_bcast_timer = delay_bcast_timer + else + if state_pwrcall[veh] == 0 then + HUD:SetItemState('siren', false) + end + AUDIO:Play('Downgrade', AUDIO.downgrade_volume) + SetLxSirenStateForVeh(veh, 0) + count_bcast_timer = delay_bcast_timer + end + end + else + HUD:ShowNotification(Lang:t('error.reg_keymap_nil_1', {i = i, proposed_tone = proposed_tone, profile_name = UTIL:GetVehicleProfileName()}), true) + HUD:ShowNotification(Lang:t('error.reg_keymap_nil_2'), true) + end + end + end + end + end) + + --CHANGE BELOW if you'd like to change which keys are used for example NUMROW1 through 0 + if i > 0 and i < 11 and main_siren_set_register_keys_set_defaults then + RegisterKeyMapping(command, description, 'keyboard', i-1) + elseif i == 11 and main_siren_set_register_keys_set_defaults then + RegisterKeyMapping(command, description, 'keyboard', '0') + else + RegisterKeyMapping(command, description, 'keyboard', '') + end + end + end +end + +--Make number into ordinal number, used for FiveM RegisterKeys +MakeOrdinal = function(number) + local sufixes = { 'th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th' } + local mod = (number % 100) + if mod == 11 or mod == 12 or mod == 13 then + return number .. 'th' + else + return number..sufixes[(number % 10) + 1] + end +end + +--------------------------------------------------------------------- +local function CleanupSounds() + if count_sndclean_timer > delay_sndclean_timer then + count_sndclean_timer = 0 + for k, v in pairs(state_lxsiren) do + if v > 0 then + if not DoesEntityExist(k) or IsEntityDead(k) then + if snd_lxsiren[k] ~= nil then + StopSound(snd_lxsiren[k]) + ReleaseSoundId(snd_lxsiren[k]) + snd_lxsiren[k] = nil + state_lxsiren[k] = nil + end + end + end + end + for k, v in pairs(state_pwrcall) do + if v > 0 then + if not DoesEntityExist(k) or IsEntityDead(k) then + if snd_pwrcall[k] ~= nil then + StopSound(snd_pwrcall[k]) + ReleaseSoundId(snd_pwrcall[k]) + snd_pwrcall[k] = nil + state_pwrcall[k] = nil + end + end + end + end + for k, v in pairs(state_airmanu) do + if v == true then + if not DoesEntityExist(k) or IsEntityDead(k) or IsVehicleSeatFree(k, -1) then + if snd_airmanu[k] ~= nil then + StopSound(snd_airmanu[k]) + ReleaseSoundId(snd_airmanu[k]) + snd_airmanu[k] = nil + state_airmanu[k] = nil + end + end + end + end + else + count_sndclean_timer = count_sndclean_timer + 1 + end +end +--------------------------------------------------------------------- +function TogIndicStateForVeh(veh, newstate) + if DoesEntityExist(veh) and not IsEntityDead(veh) then + if newstate == ind_state_o then + SetVehicleIndicatorLights(veh, 0, false) -- R + SetVehicleIndicatorLights(veh, 1, false) -- L + elseif newstate == ind_state_l then + SetVehicleIndicatorLights(veh, 0, false) -- R + SetVehicleIndicatorLights(veh, 1, true) -- L + elseif newstate == ind_state_r then + SetVehicleIndicatorLights(veh, 0, true) -- R + SetVehicleIndicatorLights(veh, 1, false) -- L + elseif newstate == ind_state_h then + SetVehicleIndicatorLights(veh, 0, true) -- R + SetVehicleIndicatorLights(veh, 1, true) -- L + end + state_indic[veh] = newstate + end +end + +--------------------------------------------------------------------- +function TogMuteDfltSrnForVeh(veh, toggle) + if DoesEntityExist(veh) and not IsEntityDead(veh) then + DisableVehicleImpactExplosionActivation(veh, toggle) + end +end + +--------------------------------------------------------------------- +function SetLxSirenStateForVeh(veh, newstate) + if DoesEntityExist(veh) and not IsEntityDead(veh) then + if newstate ~= state_lxsiren[veh] and newstate ~= nil then + if snd_lxsiren[veh] ~= nil then + StopSound(snd_lxsiren[veh]) + ReleaseSoundId(snd_lxsiren[veh]) + snd_lxsiren[veh] = nil + end + if newstate ~= 0 then + snd_lxsiren[veh] = GetSoundId() + PlaySoundFromEntity(snd_lxsiren[veh], SIRENS[newstate].String, veh, SIRENS[newstate].Ref, 0, 0) + TogMuteDfltSrnForVeh(veh, true) + end + state_lxsiren[veh] = newstate + end + end +end + +--------------------------------------------------------------------- +function SetPowercallStateForVeh(veh, newstate) + if DoesEntityExist(veh) and not IsEntityDead(veh) then + if newstate ~= state_pwrcall[veh] and newstate ~= nil then + if snd_pwrcall[veh] ~= nil then + StopSound(snd_pwrcall[veh]) + ReleaseSoundId(snd_pwrcall[veh]) + snd_pwrcall[veh] = nil + end + if newstate ~= 0 then + snd_pwrcall[veh] = GetSoundId() + PlaySoundFromEntity(snd_pwrcall[veh], SIRENS[newstate].String, veh, SIRENS[newstate].Ref, 0, 0) + end + state_pwrcall[veh] = newstate + end + end +end + +--------------------------------------------------------------------- +function SetAirManuStateForVeh(veh, newstate) + if DoesEntityExist(veh) and not IsEntityDead(veh) then + if newstate ~= state_airmanu[veh] and newstate ~= nil then + if snd_airmanu[veh] ~= nil then + StopSound(snd_airmanu[veh]) + ReleaseSoundId(snd_airmanu[veh]) + snd_airmanu[veh] = nil + end + if newstate ~= 0 then + snd_airmanu[veh] = GetSoundId() + PlaySoundFromEntity(snd_airmanu[veh], SIRENS[newstate].String, veh, SIRENS[newstate].Ref, 0, 0) + end + state_airmanu[veh] = newstate + end + end +end + +------------------------------------------------ +----------------EVENT HANDLERS------------------ +------------------------------------------------ +RegisterNetEvent('lvc:TogIndicState_c') +AddEventHandler('lvc:TogIndicState_c', function(sender, newstate) + local player_s = GetPlayerFromServerId(sender) + local ped_s = GetPlayerPed(player_s) + if DoesEntityExist(ped_s) and not IsEntityDead(ped_s) then + if ped_s ~= GetPlayerPed(-1) then + if IsPedInAnyVehicle(ped_s, false) then + local veh = GetVehiclePedIsUsing(ped_s) + TogIndicStateForVeh(veh, newstate) + end + end + end +end) + +--------------------------------------------------------------------- +RegisterNetEvent('lvc:TogDfltSrnMuted_c') +AddEventHandler('lvc:TogDfltSrnMuted_c', function(sender) + local player_s = GetPlayerFromServerId(sender) + local ped_s = GetPlayerPed(player_s) + if DoesEntityExist(ped_s) and not IsEntityDead(ped_s) then + if ped_s ~= GetPlayerPed(-1) then + if IsPedInAnyVehicle(ped_s, false) then + local veh = GetVehiclePedIsUsing(ped_s) + TogMuteDfltSrnForVeh(veh, true) + end + end + end +end) + +--------------------------------------------------------------------- +RegisterNetEvent('lvc:SetLxSirenState_c') +AddEventHandler('lvc:SetLxSirenState_c', function(sender, newstate) + local player_s = GetPlayerFromServerId(sender) + local ped_s = GetPlayerPed(player_s) + if DoesEntityExist(ped_s) and not IsEntityDead(ped_s) then + if ped_s ~= GetPlayerPed(-1) then + if IsPedInAnyVehicle(ped_s, false) then + local veh = GetVehiclePedIsUsing(ped_s) + SetLxSirenStateForVeh(veh, newstate) + end + end + end +end) + +--------------------------------------------------------------------- +RegisterNetEvent('lvc:SetPwrcallState_c') +AddEventHandler('lvc:SetPwrcallState_c', function(sender, newstate) + local player_s = GetPlayerFromServerId(sender) + local ped_s = GetPlayerPed(player_s) + if DoesEntityExist(ped_s) and not IsEntityDead(ped_s) then + if ped_s ~= GetPlayerPed(-1) then + if IsPedInAnyVehicle(ped_s, false) then + local veh = GetVehiclePedIsUsing(ped_s) + SetPowercallStateForVeh(veh, newstate) + end + end + end +end) + +--------------------------------------------------------------------- +RegisterNetEvent('lvc:SetAirManuState_c') +AddEventHandler('lvc:SetAirManuState_c', function(sender, newstate) + local player_s = GetPlayerFromServerId(sender) + local ped_s = GetPlayerPed(player_s) + if DoesEntityExist(ped_s) and not IsEntityDead(ped_s) then + if ped_s ~= GetPlayerPed(-1) then + if IsPedInAnyVehicle(ped_s, false) then + local veh = GetVehiclePedIsUsing(ped_s) + SetAirManuStateForVeh(veh, newstate) + end + end + end +end) + + +--------------------------------------------------------------------- +CreateThread(function() + while true do + CleanupSounds() + DistantCopCarSirens(false) + ----- IS IN VEHICLE ----- + if GetPedInVehicleSeat(veh, -1) == playerped then + if state_indic[veh] == nil then + state_indic[veh] = ind_state_o + end + + -- INDIC AUTO CONTROL + if actv_ind_timer == true then + if state_indic[veh] == ind_state_l or state_indic[veh] == ind_state_r then + if GetEntitySpeed(veh) < 6 then + count_ind_timer = 0 + else + if count_ind_timer > delay_ind_timer then + count_ind_timer = 0 + actv_ind_timer = false + state_indic[veh] = ind_state_o + TogIndicStateForVeh(veh, state_indic[veh]) + count_bcast_timer = delay_bcast_timer + else + count_ind_timer = count_ind_timer + 1 + end + end + end + end + + --- IS EMERG VEHICLE --- + if GetVehicleClass(veh) == 18 then + lights_on = IsVehicleSirenOn(veh) + -- FORCE RADIO ENABLED PER FRAME + if radio_masterswitch then + SetVehicleRadioEnabled(veh, true) + end + + if not IsEntityDead(veh) then + TogMuteDfltSrnForVeh(veh, true) + --- SET INIT TABLE VALUES --- + if state_lxsiren[veh] == nil then + state_lxsiren[veh] = 0 + end + if state_pwrcall[veh] == nil then + state_pwrcall[veh] = 0 + end + if state_airmanu[veh] == nil then + state_airmanu[veh] = 0 + end + + --- IF LIGHTS ARE OFF TURN OFF SIREN --- + if not lights_on and state_lxsiren[veh] > 0 then + -- SAVE TONE BEFORE TURNING OFF + if not tone_main_reset_standby then + UTIL:SetToneByID('MAIN_MEM', state_lxsiren[veh]) + end + SetLxSirenStateForVeh(veh, 0) + count_bcast_timer = delay_bcast_timer + end + if not lights_on and state_pwrcall[veh] > 0 then + SetPowercallStateForVeh(veh, 0) + count_bcast_timer = delay_bcast_timer + end + + ----- CONTROLS ----- + if not IsPauseMenuActive() and UpdateOnscreenKeyboard() ~= 0 and not radio_wheel_active then + if not key_lock then + ------ TOG DFLT SRN LIGHTS ------ + if IsDisabledControlJustReleased(0, 85) then + if lights_on then + AUDIO:Play('Off', AUDIO.off_volume) + -- SET NUI IMAGES + HUD:SetItemState('switch', false) + HUD:SetItemState('siren', false) + -- TURN OFF SIRENS (R* LIGHTS) + SetVehicleSiren(veh, false) + if trailer ~= nil and trailer ~= 0 then + SetVehicleSiren(trailer, false) + end + + else + AUDIO:Play('On', AUDIO.on_volume) -- On + -- SET NUI IMAGES + HUD:SetItemState('switch', true) + -- TURN OFF SIRENS (R* LIGHTS) + SetVehicleSiren(veh, true) + if trailer ~= nil and trailer ~= 0 then + SetVehicleSiren(trailer, true) + end + end + AUDIO:ResetActivityTimer() + count_bcast_timer = delay_bcast_timer + ------ TOG LX SIREN ------ + elseif IsDisabledControlJustReleased(0, 19) then + if state_lxsiren[veh] == 0 then + if lights_on then + AUDIO:Play('Upgrade', AUDIO.upgrade_volume) + HUD:SetItemState('siren', true) + if not tone_main_reset_standby then + -- GET THE SAVED TONE VERIFY IT IS APPROVED, AND NOT DISABLED / BUTTON ONLY + tone_mem_id = UTIL:GetToneID('MAIN_MEM') + tone_mem_option = UTIL:GetToneOption(tone_mem_id) + if UTIL:IsApprovedTone(tone_mem_id) and tone_mem_option ~= 3 and tone_mem_option ~= 4 then + SetLxSirenStateForVeh(veh, tone_mem_id) + else + new_tone = UTIL:GetNextSirenTone(tone_mem_id, veh, true) + UTIL:SetToneByID('MAIN_MEM', new_tone) + SetLxSirenStateForVeh(veh, new_tone) + end + + else + default_tone = UTIL:GetToneAtPos(2) + default_tone_option = UTIL:GetToneOption(default_tone) + if default_tone_option == 3 or default_tone_option == 4 then + new_tone = UTIL:GetNextSirenTone(default_tone, veh, true) + else + new_tone = UTIL:GetToneAtPos(2) + end + SetLxSirenStateForVeh(veh, new_tone) + end + end + else + AUDIO:Play('Downgrade', AUDIO.downgrade_volume) + -- ONLY CHANGE NUI STATE IF PWRCALL IS OFF AS WELL + if state_pwrcall[veh] == 0 then + HUD:SetItemState('siren', false) + end + if not tone_main_reset_standby then + UTIL:SetToneByID('MAIN_MEM', state_lxsiren[veh]) + end + SetLxSirenStateForVeh(veh, 0) + end + AUDIO:ResetActivityTimer() + count_bcast_timer = delay_bcast_timer + -- POWERCALL + elseif IsDisabledControlJustReleased(0, 172) and not IsMenuOpen() then + if state_pwrcall[veh] == 0 then + if lights_on then + AUDIO:Play('Upgrade', AUDIO.upgrade_volume) + HUD:SetItemState('siren', true) + SetPowercallStateForVeh(veh, UTIL:GetToneID('AUX')) + count_bcast_timer = delay_bcast_timer + end + else + AUDIO:Play('Downgrade', AUDIO.downgrade_volume) + if state_lxsiren[veh] == 0 then + HUD:SetItemState('siren', false) + end + SetPowercallStateForVeh(veh, 0) + end + AUDIO:ResetActivityTimer() + count_bcast_timer = delay_bcast_timer + end + -- CYCLE LX SRN TONES + if state_lxsiren[veh] > 0 then + if IsDisabledControlJustReleased(0, 80) then + AUDIO:Play('Upgrade', AUDIO.upgrade_volume) + HUD:SetItemState('horn', false) + SetLxSirenStateForVeh(veh, UTIL:GetNextSirenTone(state_lxsiren[veh], veh, true)) + count_bcast_timer = delay_bcast_timer + elseif IsDisabledControlPressed(0, 80) then + HUD:SetItemState('horn', true) + end + end + + -- MANU + if state_lxsiren[veh] < 1 then + if IsDisabledControlPressed(0, 80) then + AUDIO:ResetActivityTimer() + actv_manu = true + HUD:SetItemState('siren', true) + else + if actv_manu then + HUD:SetItemState('siren', false) + end + actv_manu = false + end + else + if actv_manu then + HUD:SetItemState('siren', false) + end + actv_manu = false + end + + -- HORN + if IsDisabledControlPressed(0, 86) then + actv_horn = true + AUDIO:ResetActivityTimer() + HUD:SetItemState('horn', true) + else + if actv_horn or actv_manu then + HUD:SetItemState('horn', false) + end + actv_horn = false + end + + + --AIRHORN AND MANU BUTTON SFX + if AUDIO.airhorn_button_SFX then + if IsDisabledControlJustPressed(0, 86) then + AUDIO:Play('Press', AUDIO.upgrade_volume) + end + if IsDisabledControlJustReleased(0, 86) then + AUDIO:Play('Release', AUDIO.upgrade_volume) + end + end + if AUDIO.manu_button_SFX and state_lxsiren[veh] == 0 then + if IsDisabledControlJustPressed(0, 80) then + AUDIO:Play('Press', AUDIO.upgrade_volume) + end + if IsDisabledControlJustReleased(0, 80) then + AUDIO:Play('Release', AUDIO.upgrade_volume) + end + end + else + if (IsDisabledControlJustReleased(0, 86) or + IsDisabledControlJustReleased(0, 172) or + IsDisabledControlJustReleased(0, 19) or + IsDisabledControlJustReleased(0, 85)) then + if locked_press_count % reminder_rate == 0 then + AUDIO:Play('Locked_Press', AUDIO.lock_reminder_volume, true) -- lock reminder + HUD:ShowNotification('~y~~h~Reminder:~h~ ~s~Your siren control box is ~r~locked~s~.', true) + end + locked_press_count = locked_press_count + 1 + end + end + end + + ---- ADJUST HORN / MANU STATE ---- + local hmanu_state_new = 0 + if actv_horn == true and actv_manu == false then + hmanu_state_new = UTIL:GetToneID('ARHRN') + elseif actv_horn == false and actv_manu == true then + hmanu_state_new = UTIL:GetToneID('PMANU') + elseif actv_horn == true and actv_manu == true then + hmanu_state_new = UTIL:GetToneID('SMANU') + end + if tone_airhorn_intrp then + if hmanu_state_new == UTIL:GetToneID('ARHRN') then + if state_lxsiren[veh] > 0 and actv_lxsrnmute_temp == false then + srntone_temp = state_lxsiren[veh] + SetLxSirenStateForVeh(veh, 0) + actv_lxsrnmute_temp = true + end + else + if actv_lxsrnmute_temp == true then + SetLxSirenStateForVeh(veh, srntone_temp) + actv_lxsrnmute_temp = false + end + end + end + + if state_airmanu[veh] ~= hmanu_state_new then + SetAirManuStateForVeh(veh, hmanu_state_new) + count_bcast_timer = delay_bcast_timer + end + end + else + -- DISABLE SIREN AUDIO FOR ALL VEHICLES NOT VC_EMERGENCY (VEHICLES.META) + TogMuteDfltSrnForVeh(veh, true) + end + + --- IS ANY LAND VEHICLE --- + if GetVehicleClass(veh) ~= 14 and GetVehicleClass(veh) ~= 15 and GetVehicleClass(veh) ~= 16 and GetVehicleClass(veh) ~= 21 then + ----- CONTROLS ----- + if not IsPauseMenuActive() then + -- IND L + if IsDisabledControlJustReleased(0, left_signal_key) then -- INPUT_VEH_PREV_RADIO_TRACK + local cstate = state_indic[veh] + if cstate == ind_state_l then + state_indic[veh] = ind_state_o + actv_ind_timer = false + else + state_indic[veh] = ind_state_l + actv_ind_timer = true + end + TogIndicStateForVeh(veh, state_indic[veh]) + count_ind_timer = 0 + count_bcast_timer = delay_bcast_timer + -- IND R + elseif IsDisabledControlJustReleased(0, right_signal_key) then -- INPUT_VEH_NEXT_RADIO_TRACK + local cstate = state_indic[veh] + if cstate == ind_state_r then + state_indic[veh] = ind_state_o + actv_ind_timer = false + else + state_indic[veh] = ind_state_r + actv_ind_timer = true + end + TogIndicStateForVeh(veh, state_indic[veh]) + count_ind_timer = 0 + count_bcast_timer = delay_bcast_timer + -- IND H + elseif IsControlPressed(0, hazard_key) then -- INPUT_FRONTEND_CANCEL / Backspace + if GetLastInputMethod(0) then -- last input was with kb + Wait(hazard_hold_duration) + if IsControlPressed(0, hazard_key) then -- INPUT_FRONTEND_CANCEL / Backspace + local cstate = state_indic[veh] + if cstate == ind_state_h then + state_indic[veh] = ind_state_o + AUDIO:Play('Hazards_Off', AUDIO.hazards_volume, true) -- Hazards Off + else + state_indic[veh] = ind_state_h + AUDIO:Play('Hazards_On', AUDIO.hazards_volume, true) -- Hazards On + end + TogIndicStateForVeh(veh, state_indic[veh]) + actv_ind_timer = false + count_ind_timer = 0 + count_bcast_timer = delay_bcast_timer + Wait(300) + end + end + end + end + + ----- AUTO BROADCAST VEH STATES ----- + if count_bcast_timer > delay_bcast_timer then + count_bcast_timer = 0 + --- IS EMERG VEHICLE --- + if GetVehicleClass(veh) == 18 then + TriggerServerEvent('lvc:TogDfltSrnMuted_s') + TriggerServerEvent('lvc:SetLxSirenState_s', state_lxsiren[veh]) + TriggerServerEvent('lvc:SetPwrcallState_s', state_pwrcall[veh]) + TriggerServerEvent('lvc:SetAirManuState_s', state_airmanu[veh]) + end + --- IS ANY OTHER VEHICLE --- + TriggerServerEvent('lvc:TogIndicState_s', state_indic[veh]) + else + count_bcast_timer = count_bcast_timer + 1 + end + end + end + Wait(0) + end +end) \ No newline at end of file diff --git a/resources/[EGRP-Map-Addons]/lvc/UTIL/cl_storage.lua b/resources/[EGRP-Map-Addons]/lvc/UTIL/cl_storage.lua new file mode 100644 index 000000000..9913bf28e --- /dev/null +++ b/resources/[EGRP-Map-Addons]/lvc/UTIL/cl_storage.lua @@ -0,0 +1,415 @@ +--[[ +--------------------------------------------------- +LUXART VEHICLE CONTROL V3 (FOR FIVEM) +--------------------------------------------------- +Coded by Lt.Caine +ELS Clicks by Faction +Additional Modification by TrevorBarns +--------------------------------------------------- +FILE: cl_storage.lua +PURPOSE: Handle save/load functions and version + checking +--------------------------------------------------- +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 . +--------------------------------------------------- +]] +STORAGE = { } + +local save_prefix = 'lvc_'..community_id..'_' +local repo_version = nil +local backup_tone_table = {} +local custom_tone_names = false +local SIRENS_backup_string = nil +local profiles = { } + +-- forward local fn declaration +local IsNewerVersion + +------------------------------------------------ +--Deletes all saved KVPs for that vehicle profile +-- This should never be removed. It is the only easy way for end users to delete LVC data. +RegisterCommand('lvcfactoryreset', function(source, args) + local choice = HUD:FrontEndAlert(Lang:t('warning.warning'), Lang:t('warning.factory_reset'), Lang:t('warning.facory_reset_options')) + if choice then + STORAGE:FactoryReset() + end +end) + +function STORAGE:FactoryReset() + STORAGE:DeleteKVPs(save_prefix) + STORAGE:ResetSettings() + UTIL:Print(Lang:t('info.factory_reset_success_console'), true) + HUD:ShowNotification(Lang:t('info.factory_reset_success_frontend'), true) +end + +--Prints all KVP keys and values to console +--if GetResourceMetadata(GetCurrentResourceName(), 'debug_mode', 0) == 'true' then + RegisterCommand('lvcdumpkvp', function(source, args) + UTIL:Print('^4LVC ^5STORAGE: ^7Dumping KVPs...') + local handle = StartFindKvp(save_prefix); + local key = FindKvp(handle) + while key ~= nil do + if GetResourceKvpString(key) ~= nil then + UTIL:Print('^4LVC ^5STORAGE Found: ^7"'..key..'" "'..GetResourceKvpString(key)..'", STRING', true) + elseif GetResourceKvpInt(key) ~= nil then + UTIL:Print('^4LVC ^5STORAGE Found: ^7"'..key..'" "'..GetResourceKvpInt(key)..'", INT', true) + elseif GetResourceKvpFloat(key) ~= nil then + UTIL:Print('^4LVC ^5STORAGE Found: ^7"'..key..'" "'..GetResourceKvpFloat(key)..'", FLOAT', true) + end + key = FindKvp(handle) + Wait(0) + end + UTIL:Print('^4LVC ^5STORAGE: ^7Finished Dumping KVPs...') + end) +--end +------------------------------------------------ +-- Resource Start Initialization +CreateThread(function() + TriggerServerEvent('lvc:GetRepoVersion_s') + STORAGE:FindSavedProfiles() +end) + +--[[Function for Deleting KVPs]] +function STORAGE:DeleteKVPs(prefix) + local handle = StartFindKvp(prefix); + local key = FindKvp(handle) + while key ~= nil do + DeleteResourceKvp(key) + UTIL:Print('^3LVC Info: Deleting Key \'' .. key .. '\'', true) + key = FindKvp(handle) + Wait(0) + end +end + +--[[Getter for current version used in RageUI.]] +function STORAGE:GetCurrentVersion() + local curr_version = GetResourceMetadata(GetCurrentResourceName(), 'version', 0) + if curr_version ~= nil then + return curr_version + else + return 'unknown' + end +end + +--[[Getter for repo version used in RageUI.]] +function STORAGE:GetRepoVersion() + return repo_version +end + +--[[Getter for out-of-date notification for RageUI.]] +function STORAGE:GetIsNewerVersion() + return IsNewerVersion(repo_version, STORAGE:GetCurrentVersion()) +end + +--[[Saves HUD settings, separated from SaveSettings]] +function STORAGE:SaveHUDSettings() + local hud_save_data = { Show_HUD = HUD:GetHudState(), + HUD_Scale = HUD:GetHudScale(), + HUD_pos = HUD:GetHudPosition(), + HUD_backlight_mode = HUD:GetHudBacklightMode(), + } + SetResourceKvp(save_prefix .. 'hud_data', json.encode(hud_save_data)) +end + + +--[[Saves all KVP values.]] +function STORAGE:SaveSettings() + UTIL:Print('^4LVC: ^5STORAGE: ^7Saving Settings...') + SetResourceKvp(save_prefix..'save_version', STORAGE:GetCurrentVersion()) + + --HUD Settings + STORAGE:SaveHUDSettings() + + --Tone Names + if custom_tone_names then + local tone_names = { } + for i, siren_pkg in pairs(SIRENS) do + table.insert(tone_names, siren_pkg.Name) + end + SetResourceKvp(save_prefix .. 'tone_names', json.encode(tone_names)) + UTIL:Print('^4LVC ^5STORAGE: ^7saving '..save_prefix..'tone_names...') + end + + --Profile Specific Settings + if UTIL:GetVehicleProfileName() ~= nil then + local profile_name = string.gsub(UTIL:GetVehicleProfileName(), ' ', '_') + if profile_name ~= nil then + local tone_options_encoded = json.encode(UTIL:GetToneOptionsTable()) + local profile_save_data = { PMANU = UTIL:GetToneID('PMANU'), + SMANU = UTIL:GetToneID('SMANU'), + AUX = UTIL:GetToneID('AUX'), + airhorn_intrp = tone_airhorn_intrp, + main_reset_standby = tone_main_reset_standby, + park_kill = park_kill, + tone_options = tone_options_encoded, + } + + SetResourceKvp(save_prefix .. 'profile_'..profile_name..'!', json.encode(profile_save_data)) + UTIL:Print('^4LVC ^5STORAGE: ^7saving '..save_prefix .. 'profile_'..profile_name..'!') + + --Audio Settings + local audio_save_data = { + radio_masterswitch = AUDIO.radio_masterswitch, + button_sfx_scheme = AUDIO.button_sfx_scheme, + on_volume = AUDIO.on_volume, + off_volume = AUDIO.off_volume, + upgrade_volume = AUDIO.upgrade_volume, + downgrade_volume = AUDIO.downgrade_volume, + activity_reminder_volume = AUDIO.activity_reminder_volume, + hazards_volume = AUDIO.hazards_volume, + lock_volume = AUDIO.lock_volume, + lock_reminder_volume = AUDIO.lock_reminder_volume, + airhorn_button_SFX = AUDIO.airhorn_button_SFX, + manu_button_SFX = AUDIO.manu_button_SFX, + activity_reminder_index = AUDIO:GetActivityReminderIndex(), + } + SetResourceKvp(save_prefix..'profile_'..profile_name..'_audio_data', json.encode(audio_save_data)) + UTIL:Print('^4LVC ^5STORAGE: ^7saving profile_'..profile_name..'_audio_data') + else + HUD:ShowNotification('~b~LVC: ~r~SAVE ERROR~s~: profile_name after gsub is nil.', true) + end + else + HUD:ShowNotification('~b~LVC: ~r~SAVE ERROR~s~: UTIL:GetVehicleProfileName() returned nil.', true) + end + UTIL:Print('^4LVC ^5STORAGE: ^7Finished Saving Settings...') +end + +------------------------------------------------ +--[[Loads all KVP values.]] +function STORAGE:LoadSettings(profile_name) + UTIL:Print('^4LVC ^5STORAGE: ^7Loading Settings...') + local comp_version = GetResourceMetadata(GetCurrentResourceName(), 'compatible', 0) + local save_version = GetResourceKvpString(save_prefix .. 'save_version') + local incompatible = IsNewerVersion(comp_version, save_version) == 'older' + + --Is save present if so what version + if incompatible then + AddTextEntry('lvc_mismatch_version','~y~~h~Warning:~h~ ~s~Luxart Vehicle Control Save Version Mismatch.\n~b~Compatible Version: ' .. comp_version .. '\n~o~Save Version: ' .. save_version .. '~s~\nYou may experience issues, to prevent this message from appearing verify settings and resave.') + SetNotificationTextEntry('lvc_mismatch_version') + DrawNotification(false, true) + end + + local hud_save_data = GetResourceKvpString(save_prefix..'hud_data') + if hud_save_data ~= nil then + hud_save_data = json.decode(hud_save_data) + HUD:SetHudState(hud_save_data.Show_HUD) + HUD:SetHudScale(hud_save_data.HUD_Scale) + HUD:SetHudPosition(hud_save_data.HUD_pos) + HUD:SetHudBacklightMode(hud_save_data.HUD_backlight_mode) + UTIL:Print('^4LVC ^5STORAGE: ^7loaded HUD data.') + end + + if save_version ~= nil then + --Tone Names + if main_siren_settings_masterswitch then + local tone_names = GetResourceKvpString(save_prefix..'tone_names') + if tone_names ~= nil then + tone_names = json.decode(tone_names) + for i, name in pairs(tone_names) do + if SIRENS[i] ~= nil then + SIRENS[i].Name = name + end + end + end + UTIL:Print('^4LVC ^5STORAGE: ^7loaded custom tone names.') + end + + --Profile Specific Settings + if UTIL:GetVehicleProfileName() ~= false then + local profile_name = profile_name or string.gsub(UTIL:GetVehicleProfileName(), ' ', '_') + if profile_name ~= nil then + local profile_save_data = GetResourceKvpString(save_prefix..'profile_'..profile_name..'!') + if profile_save_data ~= nil then + profile_save_data = json.decode(profile_save_data) + UTIL:SetToneByID('PMANU', profile_save_data.PMANU) + UTIL:SetToneByID('SMANU', profile_save_data.SMANU) + UTIL:SetToneByID('AUX', profile_save_data.AUX) + if main_siren_settings_masterswitch then + tone_airhorn_intrp = profile_save_data.airhorn_intrp + tone_main_reset_standby = profile_save_data.main_reset_standby + park_kill = profile_save_data.park_kill + local tone_options = json.decode(profile_save_data.tone_options) + if tone_options ~= nil then + for tone_id, option in pairs(tone_options) do + tone_id = tonumber(tone_id) + option = tonumber(option) + if SIRENS[tone_id] ~= nil then + UTIL:SetToneOption(tone_id, option) + end + end + end + end + UTIL:Print('^4LVC ^5STORAGE: ^7loaded '..profile_name..'.') + end + --Audio Settings + local audio_save_data = GetResourceKvpString(save_prefix..'profile_'..profile_name..'_audio_data') + if audio_save_data ~= nil then + audio_save_data = json.decode(audio_save_data) + if audio_save_data.radio_masterswitch ~= nil then + AUDIO.radio_masterswitch = audio_save_data.radio_masterswitch + end + AUDIO.button_sfx_scheme = audio_save_data.button_sfx_scheme + AUDIO.on_volume = audio_save_data.on_volume + AUDIO.off_volume = audio_save_data.off_volume + AUDIO.upgrade_volume = audio_save_data.upgrade_volume + AUDIO.downgrade_volume = audio_save_data.downgrade_volume + AUDIO.activity_reminder_volume = audio_save_data.activity_reminder_volume + AUDIO.hazards_volume = audio_save_data.hazards_volume + AUDIO.lock_volume = audio_save_data.lock_volume + AUDIO.lock_reminder_volume = audio_save_data.lock_reminder_volume + AUDIO.airhorn_button_SFX = audio_save_data.airhorn_button_SFX + AUDIO.manu_button_SFX = audio_save_data.manu_button_SFX + AUDIO:SetActivityReminderIndex(audio_save_data.activity_reminder_index) + UTIL:Print('^4LVC ^5STORAGE: ^7loaded audio data.') + end + else + HUD:ShowNotification('~b~LVC:~r~ LOADING ERROR~s~: profile_name after gsub is nil.', true) + end + end + end + UTIL:Print('^4LVC ^5STORAGE: ^7Finished Loading Settings...') +end + +------------------------------------------------ +--[[Resets all KVP/menu values to their default.]] +function STORAGE:ResetSettings() + UTIL:Print('^4LVC ^5STORAGE: ^7Resetting Settings...') + + --Storage State + custom_tone_names = false + profiles = { } + STORAGE:FindSavedProfiles() + + --LVC State + key_lock = false + tone_main_reset_standby = reset_to_standby_default + tone_airhorn_intrp = airhorn_interrupt_default + park_kill = park_kill_default + + --HUD State + HUD:SetHudState(hud_first_default) + HUD:SetHudScale(0.7) + HUD:ResetPosition() + HUD:SetHudBacklightMode(1) + + --Extra Tone Resets + UTIL:SetToneByPos('ARHRN', 1) + UTIL:SetToneByPos('PMANU', 2) + UTIL:SetToneByPos('SMANU', 3) + UTIL:SetToneByPos('AUX', 2) + UTIL:SetToneByPos('MAIN_MEM', 2) + + STORAGE:RestoreBackupTable() + UTIL:BuildToneOptions() + + --Audio Settings + AUDIO.radio_masterswitch = true + AUDIO.airhorn_button_SFX = false + AUDIO.manu_button_SFX = false + AUDIO:SetActivityReminderIndex(1) + + AUDIO.button_sfx_scheme = default_sfx_scheme_name + AUDIO.on_volume = default_on_volume + AUDIO.off_volume = default_off_volume + AUDIO.upgrade_volume = default_upgrade_volume + AUDIO.downgrade_volume = default_downgrade_volume + AUDIO.hazards_volume = default_hazards_volume + AUDIO.lock_volume = default_lock_volume + AUDIO.lock_reminder_volume = default_lock_reminder_volume + AUDIO.activity_reminder_volume = default_reminder_volume + UTIL:Print('^4LVC ^5STORAGE: ^7Finished Resetting Settings...') +end + +------------------------------------------------ +--[[Find all profile names of all saved KVP.]] +function STORAGE:FindSavedProfiles() + local handle = StartFindKvp(save_prefix..'profile_'); + local key = FindKvp(handle) + while key ~= nil do + if string.match(key, '(.*)!$') then + local saved_profile_name = string.match(key, save_prefix..'profile_(.*)!$') + + --Duplicate checking + local found = false + for _, profile_name in ipairs(profiles) do + if profile_name == saved_profile_name then + found = true + end + end + + if not found then + table.insert(profiles, saved_profile_name) + end + end + key = FindKvp(handle) + Wait(0) + end +end + +function STORAGE:GetSavedProfiles() + local cur_profile = UTIL:GetVehicleProfileName() + for i, profile in ipairs(profiles) do + if profile == cur_profile then + table.remove(profiles, i) + end + end + + return profiles +end +------------------------------------------------ +--[[Setter for JSON string backup of SIRENS table in case of reset since we modify SIREN table directly.]] +function STORAGE:SetBackupTable() + SIRENS_backup_string = json.encode(SIRENS) +end + +--[[Setter for SIRENS table using backup string of table.]] +function STORAGE:RestoreBackupTable() + SIRENS = json.decode(SIRENS_backup_string) +end + +--[[Setter for bool that is used in saving to determine if tone strings have been modified.]] +function STORAGE:SetCustomToneStrings(toggle) + custom_tone_names = toggle +end + +------------------------------------------------ +--HELPER FUNCTIONS for main siren settings saving:end +--Compare Version Strings: Is version newer than test_version +IsNewerVersion = function(version, test_version) + if version == nil or test_version == nil then + return 'unknown' + end + + if type(version) == 'string' then + version = semver(version) + end + if type(test_version) == 'string' then + test_version = semver(test_version) + end + + if version > test_version then + return 'older' + elseif version < test_version then + return 'newer' + elseif version == test_version then + return 'equal' + end +end + +--------------------------------------------------------------------- +--[[Callback for Server -> Client version update.]] +RegisterNetEvent('lvc:SendRepoVersion_c') +AddEventHandler('lvc:SendRepoVersion_c', function(version) + repo_version = version +end) \ No newline at end of file diff --git a/resources/[EGRP-Map-Addons]/lvc/UTIL/cl_utils.lua b/resources/[EGRP-Map-Addons]/lvc/UTIL/cl_utils.lua new file mode 100644 index 000000000..23526ebdf --- /dev/null +++ b/resources/[EGRP-Map-Addons]/lvc/UTIL/cl_utils.lua @@ -0,0 +1,434 @@ +--[[ +--------------------------------------------------- +LUXART VEHICLE CONTROL V3 (FOR FIVEM) +--------------------------------------------------- +Coded by Lt.Caine +ELS Clicks by Faction +Additional Modification by TrevorBarns +--------------------------------------------------- +FILE: cl_utils.lua +PURPOSE: Utilities for siren assignments and tables + and other common functions. +--------------------------------------------------- +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 . +--------------------------------------------------- +]] +UTIL = { } + +local approved_tones = nil +local tone_options = { } +local tone_table_names_ids = { } +local profile = nil +local tone_main_mem_id = nil +local tone_PMANU_id = nil +local tone_SMANU_id = nil +local tone_AUX_id = nil +local tone_ARHRN_id = nil + +--------------------------------------------------------------------- +--[[Return sub-table for sirens or plugin settings tables, given veh, and name of whatever setting.]] +function UTIL:GetProfileFromTable(print_name, tbl, veh, ignore_missing_default) + local ignore_missing_default = ignore_missing_default or false + local veh_name = GetDisplayNameFromVehicleModel(GetEntityModel(veh)) + local lead_and_trail_wildcard = veh_name:gsub('%d+', '#') + local lead = veh_name:match('%d*%a+') + local trail = veh_name:gsub(lead, ''):gsub('%d+', '#') + local trail_only_wildcard = string.format('%s%s', lead, trail) + + local profile_table, profile + if tbl ~= nil then + if tbl[veh_name] ~= nil then --Does profile exist as outlined in vehicle.meta + profile_table = tbl[veh_name] + profile = veh_name + UTIL:Print(Lang:t('info.profile_found', {ver = STORAGE:GetCurrentVersion(), tbl = print_name, profile = profile, model = veh_name})) + elseif tbl[trail_only_wildcard] ~= nil then --Does profile exist using # as wildcard for any trailing digits. + profile_table = tbl[trail_only_wildcard] + profile = trail_only_wildcard + UTIL:Print(Lang:t('info.profile_found', {ver = STORAGE:GetCurrentVersion(), tbl = print_name, profile = profile, model = veh_name})) + elseif tbl[lead_and_trail_wildcard] ~= nil then --Does profile exist using # as wildcard for any digits. + profile_table = tbl[lead_and_trail_wildcard] + profile = lead_and_trail_wildcard + UTIL:Print(Lang:t('info.profile_found', {ver = STORAGE:GetCurrentVersion(), tbl = print_name, profile = profile, model = veh_name})) + else + if tbl['DEFAULT'] ~= nil then + profile_table = tbl['DEFAULT'] + profile = 'DEFAULT' + UTIL:Print(Lang:t('info.profile_default_console', {ver = STORAGE:GetCurrentVersion(), tbl = print_name, model = veh_name})) + if print_name == 'SIRENS' then + HUD:ShowNotification(Lang:t('info.profile_default_frontend', {model = veh_name})) + end + else + profile_table = { } + profile = false + if not ignore_missing_default then + UTIL:Print(Lang:t('warning.profile_missing', {ver = STORAGE:GetCurrentVersion(), tbl = print_name, model = veh_name}), true) + end + end + end + else + profile_table = { } + profile = false + HUD:ShowNotification(Lang:t('error.profile_nil_table', {tbl = print_name}), true) + UTIL:Print(Lang:t('error.profile_nil_table_console', {ver = STORAGE:GetCurrentVersion(), tbl = print_name}), true) + end + + return profile_table, profile +end + +--------------------------------------------------------------------- +--[[Shorten oversized strings in SIREN_ASSIGNMENTS (SIRENS.LUA). + GTA only allows 11 characters. So to reduce confusion we'll shorten it if the user does not.]] +function UTIL:FixOversizeKeys(TABLE) + for i, tbl in pairs(TABLE) do + if string.len(i) > 11 then + local shortened_gameName = string.sub(i,1,11) + TABLE[shortened_gameName] = TABLE[i] + TABLE[i] = nil + end + end +end + +--------------------------------------------------------------------- +--[[Sets profile name and approved_tones table a copy of SIREN_ASSIGNMENTS for this vehicle]] +function UTIL:UpdateApprovedTones(veh) + approved_tones, profile = UTIL:GetProfileFromTable('SIRENS', SIREN_ASSIGNMENTS, veh) + + if profile == false then + UTIL:Print(Lang:t('error.profile_none_found_console', {game_name = GetDisplayNameFromVehicleModel(GetEntityModel(veh))}), true) + HUD:ShowNotification(Lang:t('error.profile_none_found_frontend'), true) + end + + if profile then + if not UTIL:IsApprovedTone('MAIN_MEM') then + UTIL:SetToneByPos('MAIN_MEM', 2) + end + if not UTIL:IsApprovedTone('PMANU') then + UTIL:SetToneByPos('PMANU', 2) + end + if not UTIL:IsApprovedTone('SMANU') then + UTIL:SetToneByPos('SMANU', 3) + end + if not UTIL:IsApprovedTone('AUX') then + UTIL:SetToneByPos('AUX', 2) + end + if not UTIL:IsApprovedTone('ARHRN') then + UTIL:SetToneByPos('ARHRN', 1) + end + end +end + +--[[Getter for approved_tones table, used in RageUI]] +function UTIL:GetApprovedTonesTable() + if approved_tones == nil then + if veh ~= nil then + UpdateApprovedTones(veh) + else + UpdateApprovedTones('DEFAULT') + end + end + return approved_tones +end +--------------------------------------------------------------------- +--[[Builds a table that we store tone_options in (disabled, button & cycle, cycle only, button only). + Users can set default option of siren by using optional index .Option in SIREN_ASSIGNMENTS table in SIRENS.LUA]] +function UTIL:BuildToneOptions() + local temp_array = { } + local option + for i, id in pairs(approved_tones) do + if SIRENS[id] ~= nil then + option = SIRENS[id].Option or 1 + temp_array[id] = option + end + end + tone_options = temp_array +end + +--Setter for single tone_option +function UTIL:SetToneOption(tone_id, option) + tone_options[tone_id] = option +end + +--Getter for single tone_option +function UTIL:GetToneOption(tone_id) + return tone_options[tone_id] +end + +--Getter for tone_options table (used for saving) +function UTIL:GetToneOptionsTable() + return tone_options +end +--------------------------------------------------------------------- +--[[RageUI requires a specific table layout, this builds it according to SIREN_ASSIGNMENTS > approved_tones.]] +function UTIL:GetApprovedTonesTableNameAndID() + local temp_array = { } + for i, tone_id in pairs(approved_tones) do + if i ~= 1 then + table.insert(temp_array, { Name = SIRENS[tone_id].Name, Value = tone_id } ) + end + end + return temp_array +end + +--------------------------------------------------------------------- +--[[Getter for tone id by passing string abbreviation (MAIN_MEM, PMANU, etc.)]] +function UTIL:GetToneID(tone_string) + if tone_string == 'MAIN_MEM' then + return tone_main_mem_id + elseif tone_string == 'PMANU' then + return tone_PMANU_id + elseif tone_string == 'SMANU' then + return tone_SMANU_id + elseif tone_string == 'AUX' then + return tone_AUX_id + elseif tone_string == 'ARHRN' then + return tone_ARHRN_id + end +end + +--[[Setter for ToneID by passing string abbreviation of tone (MAIN_MEM, PMANU, etc.) and position of desired tone in approved_tones.]] +function UTIL:SetToneByPos(tone_string, pos) + if profile then + if approved_tones[pos] ~= nil then + if tone_string == 'MAIN_MEM' then + tone_main_mem_id = approved_tones[pos] + elseif tone_string == 'PMANU' then + tone_PMANU_id = approved_tones[pos] + elseif tone_string == 'SMANU' then + tone_SMANU_id = approved_tones[pos] + elseif tone_string == 'AUX' then + tone_AUX_id = approved_tones[pos] + elseif tone_string == 'ARHRN' then + tone_ARHRN_id = approved_tones[pos] + end + else + HUD:ShowNotification(Lang:t('warning.too_few_tone_frontend', {code = 403}), false) + UTIL:Print(Lang:t('warning.too_few_tone_console', {ver = STORAGE:GetCurrentVersion(), code = 403, tone_string = tone_string, pos = pos}), true) + end + else + HUD:ShowNotification(Lang:t('warning.tone_position_nil_frontend', {code = 404}), false) + UTIL:Print(Lang:t('warning.tone_position_nil_console', {ver = STORAGE:GetCurrentVersion(), code = 404, tone_string = tone_string, pos = pos}), true) + end +end + +--[[Getter for position of passed tone string. Used in RageUI for P/S MANU and AUX Siren.]] +function UTIL:GetTonePos(tone_string) + local current_id = UTIL:GetToneID(tone_string) + for i, tone_id in pairs(approved_tones) do + if tone_id == current_id then + return i + end + end + return -1 +end + +--[[Getter for Tone ID at index/pos in approved_tones]] +function UTIL:GetToneAtPos(pos) + if approved_tones[pos] ~= nil then + return approved_tones[pos] + end + return nil +end + + +--[[Setter for ToneID by passing string abbreviation of tone (MAIN_MEM, PMANU, etc.) and specific ID.]] +function UTIL:SetToneByID(tone_string, tone_id) + if UTIL:IsApprovedTone(tone_id) then + if tone_string == 'MAIN_MEM' then + tone_main_mem_id = tone_id + elseif tone_string == 'PMANU' then + tone_PMANU_id = tone_id + elseif tone_string == 'SMANU' then + tone_SMANU_id = tone_id + elseif tone_string == 'AUX' then + tone_AUX_id = tone_id + elseif tone_string == 'ARHRN' then + tone_ARHRN_id = tone_id + end + else + HUD:ShowNotification(Lang:t('warning.tone_id_nil_frontend', {ver = STORAGE:GetCurrentVersion()}), false) + UTIL:Print(Lang:t('warning.tone_id_nil_console', {ver = STORAGE:GetCurrentVersion(), tone_string = tone_string, tone_id = tone_id}), true) + end +end + +--------------------------------------------------------------------- +--[[Gets next tone based off vehicle profile and current tone.]] +function UTIL:GetNextSirenTone(current_tone, veh, main_tone, last_pos) + local main_tone = main_tone or false + local last_pos = last_pos or nil + local result + + if last_pos == nil then + for i, tone_id in pairs(approved_tones) do + if tone_id == current_tone then + temp_pos = i + break + end + end + else + temp_pos = last_pos + end + + if temp_pos < #approved_tones then + temp_pos = temp_pos+1 + result = approved_tones[temp_pos] + else + temp_pos = 2 + result = approved_tones[2] + end + + if main_tone then + --Check if the tone is set to 'disable' or 'button-only' if so, find next tone + if tone_options[result] > 2 then + result = UTIL:GetNextSirenTone(result, veh, main_tone, temp_pos) + end + end + + return result +end + +--------------------------------------------------------------------- +--[[Get count of approved tones used when mapping RegisteredKeys]] +function UTIL:GetToneCount() + return #approved_tones +end + +--------------------------------------------------------------------- +--[[Ensure not all sirens are disabled / button only]] +function UTIL:IsOkayToDisable() + local count = 0 + for i, option in pairs(tone_options) do + if i ~= 1 then + if option < 3 then + count = count + 1 + end + end + end + if count > 1 then + return true + end + return false +end + +------------------------------------------------ +--[[Handle changing of tone_table custom names]] +function UTIL:ChangeToneString(tone_id, new_name) + STORAGE:SetCustomToneStrings(true) + SIRENS[tone_id].Name = new_name +end + +------------------------------------------------ +--[[Used to verify tone is allowed before playing.]] +function UTIL:IsApprovedTone(tone) + for i, approved_tone in ipairs(approved_tones) do + if approved_tone == tone then + return true + end + end + return false +end + +--------------------------------------------------------------------- +--[[Returns String used for saving, loading, and debugging]] +function UTIL:GetVehicleProfileName() + return profile +end + +--------------------------------------------------------------------- +--[[Prints to FiveM console, prints more when debug flag is enabled or overridden for important information]] +function UTIL:Print(string, override) + override = override or false + if debug_mode or override then + print(string) + end +end + +--------------------------------------------------------------------- +--[[Finds index of element in table given table and element.]] +function UTIL:IndexOf(tbl, tgt) + for i, v in pairs(tbl) do + if v == tgt then + return i + end + end + return nil +end + +--------------------------------------------------------------------- +--[[This function looks like #!*& for user convenience (and my lack of skill or abundance of laziness), + it is called when needing to change an extra, it allows users to do things like [''] = { Brake = 1 } while + also allowing advanced users to write configs like this [''] = { Brake = { add = { 3, 4 }, remove = { 5, 6 }, repair = true } } + which can add and remove multiple different extras at once and adds flag to repair the vehicle + for extras that are too large and require the vehicle to be reloaded. Once it figures out the + users config layout it calls itself again (recursive) with the id we actually need toggled right now.]] +function UTIL:TogVehicleExtras(veh, extra_id, state, repair) + local repair = repair or false + if type(extra_id) == 'table' then + -- Toggle Same Extras Mode + if extra_id.toggle ~= nil then + -- Toggle Multiple Extras + if type(extra_id.toggle) == 'table' then + for i, singe_extra_id in ipairs(extra_id.toggle) do + UTIL:TogVehicleExtras(veh, singe_extra_id, state, extra_id.repair) + end + -- Toggle a Single Extra (no table) + else + UTIL:TogVehicleExtras(veh, extra_id.toggle, state, extra_id.repair) + end + -- Toggle Different Extras Mode + elseif extra_id.add ~= nil and extra_id.remove ~= nil then + if type(extra_id.add) == 'table' then + for i, singe_extra_id in ipairs(extra_id.add) do + UTIL:TogVehicleExtras(veh, singe_extra_id, state, extra_id.repair) + end + else + UTIL:TogVehicleExtras(veh, extra_id.add, state, extra_id.repair) + end + if type(extra_id.remove) == 'table' then + for i, singe_extra_id in ipairs(extra_id.remove) do + UTIL:TogVehicleExtras(veh, singe_extra_id, not state, extra_id.repair) + end + else + UTIL:TogVehicleExtras(veh, extra_id.remove, not state, extra_id.repair) + end + end + else + if state then + if not IsVehicleExtraTurnedOn(veh, extra_id) then + local doors = { } + if repair then + for i = 0,6 do + doors[i] = GetVehicleDoorAngleRatio(veh, i) + end + end + SetVehicleAutoRepairDisabled(veh, not repair) + SetVehicleExtra(veh, extra_id, false) + UTIL:Print(Lang:t('info.extra_on', {extra = extra_id}), false) + SetVehicleAutoRepairDisabled(veh, false) + if repair then + for i = 0,6 do + if doors[i] > 0.0 then + SetVehicleDoorOpen(veh, i, true, false) + end + end + end + end + else + if IsVehicleExtraTurnedOn(veh, extra_id) then + SetVehicleExtra(veh, extra_id, true) + UTIL:Print(Lang:t('info.extra_off', {extra = extra_id}), false) + end + end + end + SetVehicleAutoRepairDisabled(veh, false) +end \ No newline at end of file diff --git a/resources/[EGRP-Map-Addons]/lvc/UTIL/semver.lua b/resources/[EGRP-Map-Addons]/lvc/UTIL/semver.lua new file mode 100644 index 000000000..8bcd88409 --- /dev/null +++ b/resources/[EGRP-Map-Addons]/lvc/UTIL/semver.lua @@ -0,0 +1,232 @@ +--[[ +Checkout semver.lua semantic versioning library for LUA +https://github.com/kikito/semver.lua + +Copyright (c) 2011 Enrique García Cota + +MIT LICENSE +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +]] + +semver = { + _VERSION = '1.2.1', + _DESCRIPTION = 'semver for Lua', + _URL = 'https://github.com/kikito/semver.lua', + _LICENSE = [[ + MIT LICENSE + Copyright (c) 2015 Enrique García Cota + Permission is hereby granted, free of charge, to any person obtaining a + copy of tother software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + The above copyright notice and tother permission notice shall be included + in all copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ]] +} + +local function checkPositiveInteger(number, name) + assert(number >= 0, name .. ' must be a valid positive number') + assert(math.floor(number) == number, name .. ' must be an integer') +end + +local function present(value) + return value and value ~= '' +end + +-- splitByDot("a.bbc.d") == {"a", "bbc", "d"} +local function splitByDot(str) + str = str or "" + local t, count = {}, 0 + str:gsub("([^%.]+)", function(c) + count = count + 1 + t[count] = c + end) + return t +end + +local function parsePrereleaseAndBuildWithSign(str) + local prereleaseWithSign, buildWithSign = str:match("^(-[^+]+)(+.+)$") + if not (prereleaseWithSign and buildWithSign) then + prereleaseWithSign = str:match("^(-.+)$") + buildWithSign = str:match("^(+.+)$") + end + assert(prereleaseWithSign or buildWithSign, ("The parameter %q must begin with + or - to denote a prerelease or a build"):format(str)) + return prereleaseWithSign, buildWithSign +end + +local function parsePrerelease(prereleaseWithSign) + if prereleaseWithSign then + local prerelease = prereleaseWithSign:match("^-(%w[%.%w-]*)$") + assert(prerelease, ("The prerelease %q is not a slash followed by alphanumerics, dots and slashes"):format(prereleaseWithSign)) + return prerelease + end +end + +local function parseBuild(buildWithSign) + if buildWithSign then + local build = buildWithSign:match("^%+(%w[%.%w-]*)$") + assert(build, ("The build %q is not a + sign followed by alphanumerics, dots and slashes"):format(buildWithSign)) + return build + end +end + +local function parsePrereleaseAndBuild(str) + if not present(str) then return nil, nil end + + local prereleaseWithSign, buildWithSign = parsePrereleaseAndBuildWithSign(str) + + local prerelease = parsePrerelease(prereleaseWithSign) + local build = parseBuild(buildWithSign) + + return prerelease, build +end + +local function parseVersion(str) + local sMajor, sMinor, sPatch, sPrereleaseAndBuild = str:match("^(%d+)%.?(%d*)%.?(%d*)(.-)$") + assert(type(sMajor) == 'string', ("Could not extract version number(s) from %q"):format(str)) + local major, minor, patch = tonumber(sMajor), tonumber(sMinor), tonumber(sPatch) + local prerelease, build = parsePrereleaseAndBuild(sPrereleaseAndBuild) + return major, minor, patch, prerelease, build +end + + +-- return 0 if a == b, -1 if a < b, and 1 if a > b +local function compare(a,b) + return a == b and 0 or a < b and -1 or 1 +end + +local function compareIds(myId, otherId) + if myId == otherId then return 0 + elseif not myId then return -1 + elseif not otherId then return 1 + end + + local selfNumber, otherNumber = tonumber(myId), tonumber(otherId) + + if selfNumber and otherNumber then -- numerical comparison + return compare(selfNumber, otherNumber) + -- numericals are always smaller than alphanums + elseif selfNumber then + return -1 + elseif otherNumber then + return 1 + else + return compare(myId, otherId) -- alphanumerical comparison + end +end + +local function smallerIdList(myIds, otherIds) + local myLength = #myIds + local comparison + + for i=1, myLength do + comparison = compareIds(myIds[i], otherIds[i]) + if comparison ~= 0 then + return comparison == -1 + end + -- if comparison == 0, continue loop + end + + return myLength < #otherIds +end + +local function smallerPrerelease(mine, other) + if mine == other or not mine then return false + elseif not other then return true + end + + return smallerIdList(splitByDot(mine), splitByDot(other)) +end + +local methods = {} + +function methods:nextMajor() + return semver(self.major + 1, 0, 0) +end +function methods:nextMinor() + return semver(self.major, self.minor + 1, 0) +end +function methods:nextPatch() + return semver(self.major, self.minor, self.patch + 1) +end + +local mt = { __index = methods } +function mt:__eq(other) + return self.major == other.major and + self.minor == other.minor and + self.patch == other.patch and + self.prerelease == other.prerelease + -- notice that build is ignored for precedence in semver 2.0.0 +end +function mt:__lt(other) + if self.major ~= other.major then return self.major < other.major end + if self.minor ~= other.minor then return self.minor < other.minor end + if self.patch ~= other.patch then return self.patch < other.patch end + return smallerPrerelease(self.prerelease, other.prerelease) + -- notice that build is ignored for precedence in semver 2.0.0 +end +-- This works like the "pessimisstic operator" in Rubygems. +-- if a and b are versions, a ^ b means "b is backwards-compatible with a" +-- in other words, "it's safe to upgrade from a to b" +function mt:__pow(other) + if self.major == 0 then + return self == other + end + return self.major == other.major and + self.minor <= other.minor +end +function mt:__tostring() + local buffer = { ("%d.%d.%d"):format(self.major, self.minor, self.patch) } + if self.prerelease then table.insert(buffer, "-" .. self.prerelease) end + if self.build then table.insert(buffer, "+" .. self.build) end + return table.concat(buffer) +end + +local function new(major, minor, patch, prerelease, build) + assert(major, "At least one parameter is needed") + + if type(major) == 'string' then + major,minor,patch,prerelease,build = parseVersion(major) + end + patch = patch or 0 + minor = minor or 0 + + checkPositiveInteger(major, "major") + checkPositiveInteger(minor, "minor") + checkPositiveInteger(patch, "patch") + + local result = {major=major, minor=minor, patch=patch, prerelease=prerelease, build=build} + return setmetatable(result, mt) +end + +setmetatable(semver, { __call = function(_, ...) return new(...) end }) +semver._VERSION= semver(semver._VERSION) + +return semver diff --git a/resources/[EGRP-Map-Addons]/lvc/UTIL/sv_lvc.lua b/resources/[EGRP-Map-Addons]/lvc/UTIL/sv_lvc.lua new file mode 100644 index 000000000..0e7ae1e04 --- /dev/null +++ b/resources/[EGRP-Map-Addons]/lvc/UTIL/sv_lvc.lua @@ -0,0 +1,190 @@ +--[[ +--------------------------------------------------- +LUXART VEHICLE CONTROL V3 (FOR FIVEM) +--------------------------------------------------- +Coded by Lt.Caine +ELS Clicks by Faction +Additional Modification by TrevorBarns +--------------------------------------------------- +FILE: server.lua +PURPOSE: Handle version checking, syncing vehicle +states. +--------------------------------------------------- +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 . +--------------------------------------------------- +]] + +local experimental = GetResourceMetadata(GetCurrentResourceName(), 'experimental', 0) == 'true' +local beta_checking = GetResourceMetadata(GetCurrentResourceName(), 'beta_checking', 0) == 'true' +local curr_version = semver(GetResourceMetadata(GetCurrentResourceName(), 'version', 0)) +local repo_version = '' +local repo_beta_version = '' + +local plugin_count = 0 +local plugins_cv = { } -- table of active plugins current versions plugins_cv = { [''] = } +local plugins_rv = { } -- table of active plugins repository versions + +---------------VEHICLE STATE EVENTS---------------- +RegisterServerEvent('lvc:GetRepoVersion_s') +AddEventHandler('lvc:GetRepoVersion_s', function() + TriggerClientEvent('lvc:SendRepoVersion_c', source, repo_version) +end) + +RegisterServerEvent('lvc:TogDfltSrnMuted_s') +AddEventHandler('lvc:TogDfltSrnMuted_s', function() + TriggerClientEvent('lvc:TogDfltSrnMuted_c', -1, source) +end) + + +RegisterServerEvent('lvc:SetLxSirenState_s') +AddEventHandler('lvc:SetLxSirenState_s', function(newstate) + TriggerClientEvent('lvc:SetLxSirenState_c', -1, source, newstate) +end) + +RegisterServerEvent('lvc:SetPwrcallState_s') +AddEventHandler('lvc:SetPwrcallState_s', function(newstate) + TriggerClientEvent('lvc:SetPwrcallState_c', -1, source, newstate) +end) + +RegisterServerEvent('lvc:SetAirManuState_s') +AddEventHandler('lvc:SetAirManuState_s', function(newstate) + TriggerClientEvent('lvc:SetAirManuState_c', -1, source, newstate) +end) + +RegisterServerEvent('lvc:TogIndicState_s') +AddEventHandler('lvc:TogIndicState_s', function(newstate) + TriggerClientEvent('lvc:TogIndicState_c', -1, source, newstate) +end) + +-------------VERSION CHECKING & STARTUP------------ +RegisterServerEvent('lvc:plugins_storePluginVersion') +AddEventHandler('lvc:plugins_storePluginVersion', function(name, version) + plugin_count = plugin_count + 1 + plugins_cv[name] = version +end) + + +CreateThread( function() +-- Get LVC version from github + PerformHttpRequest('https://raw.githubusercontent.com/TrevorBarns/luxart-vehicle-control/master/version', function(err, responseText, headers) + if responseText ~= nil and responseText ~= '' then + repo_version = semver(responseText:gsub('\n', '')) + end + end) +-- Get LVC beta version from github + PerformHttpRequest('https://raw.githubusercontent.com/TrevorBarns/luxart-vehicle-control/master/beta_version', function(err, responseText, headers) + if responseText ~= nil and responseText ~= '' then + repo_beta_version = semver(responseText:gsub('\n', '')) + end + end) + + Wait(1000) + -- Get currently installed plugin versions (plugins -> 'lvc:plugins_storePluginVersion') + TriggerEvent('lvc:plugins_getVersions') + + -- Get repo version for installed plugins + for name, _ in pairs(plugins_cv) do + PerformHttpRequest('https://raw.githubusercontent.com/TrevorBarns/luxart-vehicle-control/master/PLUGINS/'..name..'/version', function(err, responseText, headers) + if responseText ~= nil and responseText ~= '' then + plugins_rv[name] = responseText:gsub('\n', '') + else + plugins_rv[name] = 'UNKWN' + end + end) + end + Wait(1000) + print('\n\t^7 ________________________________________________________') + print('\t|\t^8 __ ^9___ ^7|') + print('\t|\t^8 / / ^7 /\\ /\\ ^9/ __\\ ^7|') + print('\t|\t^8 / / ^7\\ \\ / / ^9/ / ^7|') + print('\t|\t^8 / /___ ^7\\ V / ^9/ /___ ^7|') + print('\t|\t^8 \\____/uxart ^7\\_/ ehicle ^9\\____/ontrol ^7|') + print('\t|\t |') + print(('\t|\t COMMUNITY ID: %-23s|'):format(community_id)) + print('\t^7|________________________________________________________|') + print(('\t|\t INSTALLED: %-27s|'):format(curr_version)) + if not beta_checking then + print(('\t|\t LATEST: %-27s|'):format(repo_version)) + else + if curr_version < repo_beta_version then + print(('\t|\t ^3LATEST BETA: %-27s^7|'):format(repo_beta_version)) + end + print(('\t|\t LATEST STABLE: %-27s|'):format(repo_version)) + end + if GetResourceState('lux_vehcontrol') ~= 'started' and GetResourceState('lux_vehcontrol') ~= 'starting' then + if GetCurrentResourceName() == 'lvc' then + if community_id ~= nil and community_id ~= '' then + -- STABLE UPDATE DETECTED + if curr_version < repo_version then + print('\t^7|________________________________________________________|') + print('\t|\t ^8STABLE UPDATE AVAILABLE ^7|') + print('\t|^8 DOWNLOAD AT: ^7|') + print('\t|^2 github.com/TrevorBarns/luxart-vehicle-control/releases ^7|') + elseif beta_checking and curr_version < repo_beta_version then + print('\t^7|________________________________________________________|') + print('\t|\t ^4BETA UPDATE AVAILABLE ^7|') + print('\t|^4 DOWNLOAD AT: ^7|') + print('\t|^2 github.com/TrevorBarns/luxart-vehicle-control/releases ^7|') + -- EXPERMENTAL VERSION + elseif curr_version > repo_version or curr_version == repo_beta_version then + print('\t^7|________________________________________________________|') + print('\t|\t ^3BETA VERSION ^7|') + -- IS THE USER AWARE THEY DOWNLOADED EXPERMENTAL CHECK CONVARS + if not experimental then + print('\t|^3 THIS VERSION IS IN DEVELOPMENT AND IS NOT RECOMMENDED ^7|') + print('\t|^3 BUGS MAY EXIST. IF THIS WAS A MISTAKE DOWNLOAD THE ^7|') + print('\t|^3 LATEST STABLE RELEASE AT: ^7|') + print('\t|^2 github.com/TrevorBarns/luxart-vehicle-control/releases ^7|') + print('\t|^3 TO MUTE THIS: SET CONVAR \'experimental\' to \'true\' ^7|') + end + end + + -- IF PLUGINS ARE INSTALLED + if plugin_count > 0 then + print('\t^7|________________________________________________________|') + print('\t^7|INSTALLED PLUGINS | INSTALLED | LATEST |') + for name, version in pairs(plugins_cv) do + local plugin_string + if plugins_rv[name] ~= nil and plugins_rv[name] ~= 'UNKWN' and plugins_cv[name] < plugins_rv[name] then + plugin_string = ('\t|^8 %-30s^7|^8 %s ^7|^8 %s ^7|^8 UPDATE REQUIRED ^7'):format(name, plugins_cv[name], plugins_rv[name]) + elseif plugins_rv[name] ~= nil and plugins_cv[name] > plugins_rv[name] or plugins_rv[name] == 'UNKWN' then + plugin_string = ('\t|^3 %-30s^7|^3 %s ^7|^3 %s ^7|^3 EXPERIMENTAL VERSION ^7'):format(name, plugins_cv[name], plugins_rv[name]) + else + plugin_string = ('\t| %-30s| %s | %s |'):format(name, plugins_cv[name], plugins_rv[name]) + end + print(plugin_string) + end + end + else -- NO COMMUNITY ID SET + print('\t|\t^8 CONFIGURATION ERROR ^7|') + print('\t|^8 COMMUNITY ID MISSING, THIS IS REQUIRED TO PREVENT ^7|') + print('\t|^8 CONFLICTS FOR PLAYERS WHO PLAY ON MULTIPLE SERVERS ^7|') + print('\t|^8 WITH LVC. PLEASE SET THIS IN SETTINGS.LUA. ^7|') + end + else -- INCORRECT RESOURCE NAME + print('\t|\t^8 CONFIGURATION ERROR ^7|') + print('\t|^8 INVALID RESOURCE NAME. PLEASE VERIFY RESOURCE FOLDER ^7|') + print('\t|^8 NAME READS \'^3lvc^8\' (CASE-SENSITIVE). THIS IS REQUIRED ^7|') + print('\t|^8 FOR PROPER SAVE / LOAD FUNCTIONALITY. PLEASE RENAME, ^7|') + print('\t|^8 REFRESH, AND ENSURE. ^7|') + end + else -- RESOURCE CONFLICT + print('\t|\t^8 RESOURCE CONFLICT DETECTED ^7|') + print('\t|^8 DETECTED "lux_vehcontrol" RUNNING, THIS CONFLICTS WITH ^7|') + print('\t|^8 LVC. PLEASE STOP "lux_vehcontrol" AND RESTART LVC. ^7|') + end + print('\t^7|________________________________________________________|') + print('\t^7| Updates, Support, Feedback: ^5discord.link/LVC ^7|') + print('\t^7|________________________________________________________|\n\n') +end) \ No newline at end of file diff --git a/resources/[EGRP-Map-Addons]/lvc/fxmanifest.lua b/resources/[EGRP-Map-Addons]/lvc/fxmanifest.lua new file mode 100644 index 000000000..739a9b259 --- /dev/null +++ b/resources/[EGRP-Map-Addons]/lvc/fxmanifest.lua @@ -0,0 +1,86 @@ +------------------------------ + +fx_version 'adamant' +games { 'gta5' } + +author 'TrevorBarns w/ credits see GitHub' +description 'A siren / emergency lights controller for FiveM.' + +version '3.2.9' -- Readonly version of currently installed version. +compatible '3.2.2' -- Readonly save reverse compatiability. + +------------------------------ + +beta_checking 'true' -- Notifications for beta revisions and new betas. +experimental 'false' -- Mute unstable version warning in server console. +debug_mode 'false' -- More verbose printing on client console. + +------------------------------ + +ui_page('/UI/html/index.html') + +dependencies { + 'RageUI' +} + +files({ + 'UI/html/index.html', + 'UI/html/lvc.js', + 'UI/html/style.css', + 'UI/sounds/*.ogg', + 'UI/sounds/**/*.ogg', + 'UI/textures/**/*.png', + 'UI/textures/**/*.gif', + 'PLUGINS/**/*.json' +}) + + +shared_script { + '/UTIL/semver.lua', + '/UI/cl_locale.lua', + '/UI/locale/en.lua', -- Set locale / language file here. + 'SETTINGS.lua', +} + +client_scripts { + ---------------RAGE-UI--------------- + '@RageUI/RMenu.lua', + '@RageUI/menu/RageUI.lua', + '@RageUI/menu/Menu.lua', + '@RageUI/menu/MenuController.lua', + '@RageUI/components/Audio.lua', + '@RageUI/components/Enum.lua', + '@RageUI/components/Keys.lua', + '@RageUI/components/Rectangle.lua', + '@RageUI/components/Sprite.lua', + '@RageUI/components/Text.lua', + '@RageUI/components/Visual.lua', + '@RageUI/menu/elements/ItemsBadge.lua', + '@RageUI/menu/elements/ItemsColour.lua', + '@RageUI/menu/elements/PanelColour.lua', + '@RageUI/menu/items/UIButton.lua', + '@RageUI/menu/items/UICheckBox.lua', + '@RageUI/menu/items/UIList.lua', + '@RageUI/menu/items/UISeparator.lua', + '@RageUI/menu/items/UISlider.lua', + '@RageUI/menu/items/UISliderHeritage.lua', + '@RageUI/menu/items/UISliderProgress.lua', + '@RageUI/menu/panels/UIColourPanel.lua', + '@RageUI/menu/panels/UIGridPanel.lua', + '@RageUI/menu/panels/UIPercentagePanel.lua', + '@RageUI/menu/panels/UIStatisticsPanel.lua', + '@RageUI/menu/windows/UIHeritage.lua', + ------------------------------------- + 'SIRENS.lua', + '/UTIL/cl_*.lua', + '/UI/cl_*.lua', + '/PLUGINS/cl_plugins.lua', + '/PLUGINS/**/SETTINGS.lua', + '/PLUGINS/**/cl_*.lua', +} + +server_script { + '/UTIL/sv_lvc.lua', + '/PLUGINS/**/sv_*.lua' +} +------------------------------ \ No newline at end of file diff --git a/resources/[EGRP-Map-Addons]/lvc/version b/resources/[EGRP-Map-Addons]/lvc/version new file mode 100644 index 000000000..132d9f770 --- /dev/null +++ b/resources/[EGRP-Map-Addons]/lvc/version @@ -0,0 +1 @@ +3.2.8 \ No newline at end of file